diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/World.java b/src/main/java/de/bixilon/minosoft/game/datatypes/World.java index 0e0e729d2..6f53a02c9 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/World.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/World.java @@ -23,8 +23,8 @@ import java.util.Map; * Collection of ChunkColumns */ public class World { - public final HashMap chunks; - public final HashMap entities; + final HashMap chunks; + final HashMap entities; final String name; boolean hardcore; boolean raining; @@ -87,4 +87,16 @@ public class World { public void setRaining(boolean raining) { this.raining = raining; } + + public void addEntity(Entity entity) { + this.entities.put(entity.getId(), entity); + } + + public Entity getEntity(int id) { + return entities.get(id); + } + + public void removeEntity(Entity entity) { + this.entities.remove(entity.getId()); + } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Entity.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Entity.java index 6f193324c..7995c5832 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Entity.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Entity.java @@ -14,7 +14,7 @@ package de.bixilon.minosoft.game.datatypes.entities; public interface Entity { - Entities getEntityType(); + Mobs getEntityType(); int getId(); diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Mob.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Mob.java new file mode 100644 index 000000000..87e289987 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Mob.java @@ -0,0 +1,20 @@ +/* + * 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; + +public interface Mob extends Entity { + float getHealth(); + + void setHealth(float health); +} diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Entities.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Mobs.java similarity index 84% rename from src/main/java/de/bixilon/minosoft/game/datatypes/entities/Entities.java rename to src/main/java/de/bixilon/minosoft/game/datatypes/entities/Mobs.java index df3b2fda1..2b5207baa 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Entities.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Mobs.java @@ -15,21 +15,21 @@ package de.bixilon.minosoft.game.datatypes.entities; import de.bixilon.minosoft.game.datatypes.Identifier; -public enum Entities { +public enum Mobs { ZOMBIE(new Identifier("zombie"), 54, Zombie.class); final Identifier identifier; final int type; final Class clazz; - Entities(Identifier identifier, int type, Class clazz) { + Mobs(Identifier identifier, int type, Class clazz) { this.identifier = identifier; this.type = type; this.clazz = clazz; } - public static Entities byIdentifier(Identifier identifier) { - for (Entities b : values()) { + public static Mobs byIdentifier(Identifier identifier) { + for (Mobs b : values()) { if (b.getIdentifier().equals(identifier)) { return b; } @@ -37,8 +37,8 @@ public enum Entities { return null; } - public static Entities byType(int type) { - for (Entities b : values()) { + public static Mobs byType(int type) { + for (Mobs b : values()) { if (b.getType() == type) { return b; } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Zombie.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Zombie.java index 84a3e0f4c..f4a0cea49 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Zombie.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/Zombie.java @@ -13,21 +13,28 @@ package de.bixilon.minosoft.game.datatypes.entities; -public class Zombie implements Entity { + +public class Zombie implements Mob { final int id; Location location; Velocity velocity; int yaw; int pitch; - EntityMetaData data; + EntityMetaData metaData; + float health; - public Zombie(int id) { + public Zombie(int id, Location location, int yaw, int pitch, Velocity velocity, EntityMetaData metaData) { this.id = id; + this.location = location; + this.yaw = yaw; + this.pitch = pitch; + this.velocity = velocity; + this.metaData = metaData; } @Override - public Entities getEntityType() { - return Entities.ZOMBIE; + public Mobs getEntityType() { + return Mobs.ZOMBIE; } public int getId() { @@ -79,21 +86,31 @@ public class Zombie implements Entity { @Override public float getWidth() { - return 0; + return 0.6F; } @Override public float getHeight() { - return 0; + return 1.95F; } @Override public EntityMetaData getMetaData() { - return data; + return metaData; } @Override public void setMetaData(EntityMetaData data) { - this.data = data; + this.metaData = data; + } + + @Override + public float getHealth() { + return health; + } + + @Override + public void setHealth(float health) { + this.health = health; } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnMob.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnMob.java new file mode 100644 index 000000000..7d1e35d91 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnMob.java @@ -0,0 +1,64 @@ +/* + * 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.entities.*; +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.lang.reflect.InvocationTargetException; + +public class PacketSpawnMob implements ClientboundPacket { + Mob mob; + + @Override + public void read(InPacketBuffer buffer, ProtocolVersion v) { + switch (v) { + case VERSION_1_7_10: + int entityId = buffer.readVarInt(); + Mobs type = Mobs.byType(buffer.readByte()); + Location location = new Location(buffer.readFixedPointNumber(), buffer.readFixedPointNumber(), buffer.readFixedPointNumber()); + int yaw = buffer.readByte(); //ToDo + int pitch = buffer.readByte(); + int headPitch = buffer.readByte(); + Velocity velocity = new Velocity(buffer.readShort(), buffer.readShort(), buffer.readShort()); + EntityMetaData metaData = buffer.readEntityMetaData(); + + assert type != null; + try { + mob = (Mob) type.getClazz().getConstructor(int.class, Location.class, int.class, int.class, Velocity.class, EntityMetaData.class).newInstance(entityId, location, yaw, pitch, velocity, metaData); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + e.printStackTrace(); + } + break; + } + } + + @Override + public void log() { + Log.protocol(String.format("Mob spawned (entityId=%d, type=%s, at %s %s %s)", mob.getId(), mob.getEntityType().name(), mob.getLocation().getX(), mob.getLocation().getY(), mob.getLocation().getZ())); + } + + public Mob getMob() { + return mob; + } + + @Override + public void handle(PacketHandler h) { + h.handle(this); + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java index 57f36dc1a..da90647cb 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/InByteBuffer.java @@ -15,6 +15,7 @@ package de.bixilon.minosoft.protocol.protocol; import de.bixilon.minosoft.game.datatypes.BlockPosition; import de.bixilon.minosoft.game.datatypes.ChatComponent; +import de.bixilon.minosoft.game.datatypes.entities.EntityMetaData; import org.json.JSONObject; import java.nio.ByteBuffer; @@ -141,6 +142,10 @@ public class InByteBuffer { return result; } + public double readFixedPointNumber() { + return readInteger() / 32.0D; + } + public JSONObject readJson() { return new JSONObject(readString()); } @@ -170,4 +175,9 @@ public class InByteBuffer { public int getBytesLeft() { return bytes.length - pos; } + + public EntityMetaData readEntityMetaData() { + //ToDo + return null; + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java index 4233625bc..2d65d4e49 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java @@ -136,6 +136,10 @@ public class OutByteBuffer { } while (value != 0); } + public void writeFixedPointNumber(double d) { + writeInteger((int) (d * 32.0D)); + } + public List getBytes() { return bytes; } 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 821075125..505863d31 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -142,4 +142,8 @@ public class PacketHandler { //ToDo: handle all updates } } + + public void handle(PacketSpawnMob pkg) { + connection.getPlayer().getWorld().addEntity(pkg.getMob()); + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/Packets.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/Packets.java index 2446cbee0..c94cd87de 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/Packets.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/Packets.java @@ -78,7 +78,7 @@ public class Packets { LOGIN_LOGIN_SUCCESS, LOGIN_SET_COMPRESSION, LOGIN_PLUGIN_REQUEST, - PLAY_SPAWN_ENTITY, + PLAY_SPAWN_MOB, PLAY_SPAWN_EXPERIENCE_ORB, PLAY_SPAWN_WEATHER_ENTITY, PLAY_SPAWN_LIVING_ENTITY, @@ -174,7 +174,7 @@ public class Packets { PLAY_UPDATE_VIEW_DISTANCE, PLAY_CHUNK_BULK, PLAY_UPDATE_SIGN, - PLAY_STATISTICS - + PLAY_STATISTICS, + PLAY_SPAWN_OBJECT } } 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 adab72598..34feb9e46 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java @@ -62,5 +62,6 @@ public interface Protocol { packetClassMapping.put(Packets.Clientbound.PLAY_HELD_ITEM_CHANGE, PacketHeldItemChangeReceiving.class); packetClassMapping.put(Packets.Clientbound.PLAY_SET_EXPERIENCE, PacketSetExperience.class); packetClassMapping.put(Packets.Clientbound.PLAY_CHANGE_GAME_STATE, PacketChangeGameState.class); + packetClassMapping.put(Packets.Clientbound.PLAY_SPAWN_MOB, PacketSpawnMob.class); } } \ No newline at end of file diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol_1_7_10.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol_1_7_10.java index 8f20fe8f9..d07cb5979 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol_1_7_10.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol_1_7_10.java @@ -81,8 +81,9 @@ public class Protocol_1_7_10 implements Protocol { clientboundPacketMapping.put(Packets.Clientbound.PLAY_USE_BED, 0x0A); clientboundPacketMapping.put(Packets.Clientbound.PLAY_ENTITY_ANIMATION, 0x0B); clientboundPacketMapping.put(Packets.Clientbound.PLAY_SPAWN_PLAYER, 0x0C); - clientboundPacketMapping.put(Packets.Clientbound.PLAY_COLLECT_ITEM, 0x0E); - clientboundPacketMapping.put(Packets.Clientbound.PLAY_SPAWN_ENTITY, 0x0F); + clientboundPacketMapping.put(Packets.Clientbound.PLAY_COLLECT_ITEM, 0x0D); + clientboundPacketMapping.put(Packets.Clientbound.PLAY_SPAWN_OBJECT, 0x0E); + clientboundPacketMapping.put(Packets.Clientbound.PLAY_SPAWN_MOB, 0x0F); clientboundPacketMapping.put(Packets.Clientbound.PLAY_SPAWN_PAINTING, 0x10); clientboundPacketMapping.put(Packets.Clientbound.PLAY_SPAWN_EXPERIENCE_ORB, 0x11); clientboundPacketMapping.put(Packets.Clientbound.PLAY_ENTITY_VELOCITY, 0x12);