diff --git a/src/main/java/de/bixilon/minosoft/EntityPropertyModifier.java b/src/main/java/de/bixilon/minosoft/EntityPropertyModifier.java new file mode 100644 index 000000000..603511fa8 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/EntityPropertyModifier.java @@ -0,0 +1,30 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft; + +public class EntityPropertyModifier { + double amount; + + public EntityPropertyModifier(double amount) { + this.amount = amount; + } + + public double getAmount() { + return amount; + } + + public void setAmount(double amount) { + this.amount = amount; + } +} diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/EntityProperty.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/EntityProperty.java new file mode 100644 index 000000000..c11eddf39 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/EntityProperty.java @@ -0,0 +1,36 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.game.datatypes.entities; + +import de.bixilon.minosoft.EntityPropertyModifier; + +import java.util.HashMap; +import java.util.UUID; + +public class EntityProperty { + final double value; + HashMap modifiers = new HashMap<>(); + + public EntityProperty(double value) { + this.value = value; + } + + public double getValue() { + return value; + } + + public HashMap getModifiers() { + return modifiers; + } +} diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/EntityPropertyKey.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/EntityPropertyKey.java new file mode 100644 index 000000000..5cea18c38 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/EntityPropertyKey.java @@ -0,0 +1,45 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.game.datatypes.entities; + +import de.bixilon.minosoft.game.datatypes.Identifier; + +public enum EntityPropertyKey { + MAX_HEALTH(new Identifier("generic.maxHealth")), + FOLLOW_RANGE(new Identifier("generic.followRange")), + KNOCKBACK_RESISTANCE(new Identifier("generic.knockbackResistance")), + MOVEMENT_SPEED(new Identifier("generic.movementSpeed")), + ATTACK_DAMAGE(new Identifier("generic.attackDamage")), + HORSE_JUMP_STRENGTH(new Identifier("horse.jumpStrength")), + ZOMBIE_SPAWN_REINFORCEMENT(new Identifier("zombie.spawnReinforcements")); + + final Identifier identifier; + + EntityPropertyKey(Identifier identifier) { + this.identifier = identifier; + } + + public static EntityPropertyKey byIdentifier(Identifier identifier) { + for (EntityPropertyKey b : values()) { + if (b.getIdentifier().equals(identifier)) { + return b; + } + } + return null; + } + + public Identifier getIdentifier() { + return identifier; + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEntityProperties.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEntityProperties.java new file mode 100644 index 000000000..6c5213e8f --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEntityProperties.java @@ -0,0 +1,111 @@ +/* + * Codename Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.protocol.packets.clientbound.play; + +import de.bixilon.minosoft.game.datatypes.Identifier; +import de.bixilon.minosoft.game.datatypes.entities.EntityProperty; +import de.bixilon.minosoft.game.datatypes.entities.EntityPropertyKey; +import de.bixilon.minosoft.logging.Log; +import de.bixilon.minosoft.protocol.packets.ClientboundPacket; +import de.bixilon.minosoft.protocol.protocol.InPacketBuffer; +import de.bixilon.minosoft.protocol.protocol.PacketHandler; +import de.bixilon.minosoft.protocol.protocol.ProtocolVersion; + +import java.util.HashMap; +import java.util.UUID; + +public class PacketEntityProperties implements ClientboundPacket { + int entityId; + HashMap properties = new HashMap<>(); + + + @Override + public void read(InPacketBuffer buffer, ProtocolVersion v) { + switch (v) { + case VERSION_1_7_10: { + entityId = buffer.readInteger(); + int count = buffer.readInteger(); + for (int i = 0; i < count; i++) { + EntityPropertyKey key = EntityPropertyKey.byIdentifier(new Identifier(buffer.readString())); + double value = buffer.readDouble(); + short listLength = buffer.readShort(); + for (int ii = 0; ii < listLength; ii++) { + UUID uuid = buffer.readUUID(); + double amount = buffer.readDouble(); + ModifierAction operation = ModifierAction.byId(buffer.readByte()); + //ToDo: modifiers + } + properties.put(key, new EntityProperty(value)); + } + break; + } + case VERSION_1_8: { + entityId = buffer.readVarInt(); + int count = buffer.readInteger(); + for (int i = 0; i < count; i++) { + EntityPropertyKey key = EntityPropertyKey.byIdentifier(new Identifier(buffer.readString())); + double value = buffer.readDouble(); + int listLength = buffer.readVarInt(); + for (int ii = 0; ii < listLength; ii++) { + UUID uuid = buffer.readUUID(); + double amount = buffer.readDouble(); + ModifierAction operation = ModifierAction.byId(buffer.readByte()); + //ToDo: modifiers + } + properties.put(key, new EntityProperty(value)); + } + break; + } + } + } + + @Override + public void log() { + Log.protocol(String.format("Received entity properties (entityId=%d)", entityId)); + } + + @Override + public void handle(PacketHandler h) { + h.handle(this); + } + + public int getEntityId() { + return entityId; + } + + public enum ModifierAction { + ADD(0), + ADD_PERCENT(1), + MULTIPLY(2); + + final int id; + + ModifierAction(int id) { + this.id = id; + } + + public static ModifierAction byId(int id) { + for (ModifierAction a : values()) { + if (a.getId() == id) { + return a; + } + } + return null; + } + + public int getId() { + return id; + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerInfo.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerInfo.java index 92d28b2c1..f8e340bec 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerInfo.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketPlayerInfo.java @@ -86,7 +86,7 @@ public class PacketPlayerInfo implements ClientboundPacket { public void log() { for (PlayerInfoBulk property : infos) { if (property.isLegacy()) { - Log.game(String.format("[TAB] Player info bulk (uuid=%s)", property.getUUID())); + Log.game(String.format("[TAB] Player info bulk (uuid=%s, name=%s, ping=%d)", property.getUUID(), property.getName(), property.getPing())); } else { Log.game(String.format("[TAB] Player info bulk (uuid=%s, action=%s, name=%s, gameMode=%s, ping=%d)", property.getUUID(), property.getAction(), property.getName(), ((property.getGameMode() == null) ? "null" : property.getGameMode().name()), property.getPing())); diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java index 77e33e6c1..7f4dce327 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -125,6 +125,11 @@ public class PacketHandler { break; case REMOVE_PLAYER: if (bulk.isLegacy()) { + PlayerInfo info = connection.getPlayer().getPlayerInfo(bulk.getName()); + if (info == null) { + // not initialized yet + return; + } connection.getPlayer().getPlayerInfos().remove(connection.getPlayer().getPlayerInfo(bulk.getName()).getUUID()); return; } @@ -485,7 +490,11 @@ public class PacketHandler { } public void handle(PackerResourcePackSend pkg) { - //ToDo ask user, download pack. for now send an okay + //ToDo ask user, download pack. for now just send an okay connection.sendPacket(new PacketResourcePackStatus(pkg.getHash(), PacketResourcePackStatus.ResourcePackStatus.SUCCESSFULLY)); } + + public void handle(PacketEntityProperties pkg) { + //ToDo + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java index 56c3aff43..2df8b9881 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java @@ -116,6 +116,7 @@ public abstract class Protocol implements ProtocolInterface { packetClassMapping.put(Packets.Clientbound.PLAY_SERVER_DIFFICULTY, PacketServerDifficulty.class); packetClassMapping.put(Packets.Clientbound.PLAY_LIST_HEADER_AND_FOOTER, PacketTabHeaderAndFooter.class); packetClassMapping.put(Packets.Clientbound.PLAY_RESOURCE_PACK_SEND, PackerResourcePackSend.class); + packetClassMapping.put(Packets.Clientbound.PLAY_ENTITY_PROPERTIES, PacketEntityProperties.class); } public static ProtocolVersion getLowestVersionSupported() {