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 ecb71ebb2..ccbc5e24c 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 @@ -17,11 +17,14 @@ import de.bixilon.minosoft.game.datatypes.Slot; import de.bixilon.minosoft.game.datatypes.Slots; import de.bixilon.minosoft.game.datatypes.entities.meta.EntityMetaData; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; public abstract class Entity implements EntityInterface { final int id; final HashMap equipment; + final List effectList; Location location; Velocity velocity; int yaw; @@ -35,6 +38,7 @@ public abstract class Entity implements EntityInterface { this.pitch = pitch; this.velocity = velocity; this.equipment = new HashMap<>(); + this.effectList = new ArrayList<>(); } @@ -103,4 +107,17 @@ public abstract class Entity implements EntityInterface { return EntityMetaData.class; } + public List getEffectList() { + return effectList; + } + + public void addEffect(StatusEffect effect) { + // effect already applied, maybe the duration or the amplifier changed? + effectList.removeIf(listEffect -> listEffect.getEffect() == effect.getEffect()); + effectList.add(effect); + } + + public void removeEffect(StatusEffects effect) { + effectList.removeIf(listEffect -> listEffect.getEffect() == effect); + } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/StatusEffect.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/StatusEffect.java index 7cc5aeb4c..8d51aedfe 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/StatusEffect.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/StatusEffect.java @@ -13,78 +13,31 @@ package de.bixilon.minosoft.game.datatypes.entities; -public enum StatusEffect { - SPEED("speed", 1, Impact.POSITIVE), - SLOWNESS("slowness", 2, Impact.NEGATIVE), - HASTE("haste", 3, Impact.POSITIVE), - MINING_FATIGUE("mining_fatigue", 4, Impact.NEGATIVE), - STRENGTH("strength", 5, Impact.POSITIVE), - INSTANT_HEALTH("instant_health", 6, Impact.POSITIVE), - INSTANT_DAMAGE("instant_damage", 7, Impact.POSITIVE), - JUMP_BOOST("jump_boost", 8, Impact.POSITIVE), - NAUSEA("nausea", 9, Impact.NEGATIVE), - REGENERATION("regeneration", 10, Impact.POSITIVE), - RESISTANCE("resistance", 11, Impact.POSITIVE), - FIRE_RESISTANCE("fire_resistance", 12, Impact.POSITIVE), - WATER_BREATHING("water_breathing", 13, Impact.POSITIVE), - INVISIBILITY("invisibility", 14, Impact.POSITIVE), - BLINDNESS("blindness", 15, Impact.NEGATIVE), - NIGHT_VISION("night_vision", 16, Impact.POSITIVE), - HUNGER("hunger", 17, Impact.NEGATIVE), - WEAKNESS("weakness", 18, Impact.NEGATIVE), - POISON("poison", 19, Impact.NEGATIVE), - WITHER("wither", 20, Impact.NEGATIVE), - HEALTH_BOOST("health_boost", 21, Impact.POSITIVE), - ABSORPTION("absorption", 22, Impact.POSITIVE), - SATURATION("saturation", 23, Impact.POSITIVE), - GLOWING("glowing", 24, Impact.NEGATIVE), - LEVITATION("levitation", 25, Impact.NEGATIVE), - LUCK("luck", 26, Impact.POSITIVE), - UNLUCK("unluck", 27, Impact.NEGATIVE), - SLOW_FALLING("slow_falling", 28, Impact.POSITIVE), - CONDUIT_POWER("conduit_power", 29, Impact.POSITIVE), - DOLPHINS_GRACE("dolphins_grace", 30, Impact.POSITIVE), - BAD_OMEN("bad_omen", 31, Impact.NEGATIVE), - HERO_OF_THE_VILLAGE("hero_of_the_village", 32, Impact.POSITIVE); +public class StatusEffect { + StatusEffects effect; + byte amplifier; + short duration; - final String name; - final int id; - final Impact impact; - - StatusEffect(String name, int id, Impact impact) { - this.name = name; - this.id = id; - this.impact = impact; + public StatusEffect(StatusEffects effect, byte amplifier, short duration) { + this.effect = effect; + this.amplifier = amplifier; + this.duration = duration; } - public static StatusEffect byId(int id) { - for (StatusEffect s : values()) { - if (s.getId() == id) { - return s; - } - } - return null; + public byte getAmplifier() { + return amplifier; } - public static StatusEffect byName(String name) { - for (StatusEffect s : values()) { - if (s.getName().equals(name)) { - return s; - } - } - return null; + public short getDuration() { + return duration; } - public String getName() { - return name; + public StatusEffects getEffect() { + return effect; } - public int getId() { - return id; - } - - public enum Impact { - POSITIVE, - NEGATIVE + @Override + public String toString() { + return String.format("%s (amplifier: %d, duration: %d)", effect.name(), amplifier, duration); } } diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/entities/StatusEffects.java b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/StatusEffects.java new file mode 100644 index 000000000..a0b09dba7 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/entities/StatusEffects.java @@ -0,0 +1,90 @@ +/* + * 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 enum StatusEffects { + SPEED("speed", 1, Impact.POSITIVE), + SLOWNESS("slowness", 2, Impact.NEGATIVE), + HASTE("haste", 3, Impact.POSITIVE), + MINING_FATIGUE("mining_fatigue", 4, Impact.NEGATIVE), + STRENGTH("strength", 5, Impact.POSITIVE), + INSTANT_HEALTH("instant_health", 6, Impact.POSITIVE), + INSTANT_DAMAGE("instant_damage", 7, Impact.POSITIVE), + JUMP_BOOST("jump_boost", 8, Impact.POSITIVE), + NAUSEA("nausea", 9, Impact.NEGATIVE), + REGENERATION("regeneration", 10, Impact.POSITIVE), + RESISTANCE("resistance", 11, Impact.POSITIVE), + FIRE_RESISTANCE("fire_resistance", 12, Impact.POSITIVE), + WATER_BREATHING("water_breathing", 13, Impact.POSITIVE), + INVISIBILITY("invisibility", 14, Impact.POSITIVE), + BLINDNESS("blindness", 15, Impact.NEGATIVE), + NIGHT_VISION("night_vision", 16, Impact.POSITIVE), + HUNGER("hunger", 17, Impact.NEGATIVE), + WEAKNESS("weakness", 18, Impact.NEGATIVE), + POISON("poison", 19, Impact.NEGATIVE), + WITHER("wither", 20, Impact.NEGATIVE), + HEALTH_BOOST("health_boost", 21, Impact.POSITIVE), + ABSORPTION("absorption", 22, Impact.POSITIVE), + SATURATION("saturation", 23, Impact.POSITIVE), + GLOWING("glowing", 24, Impact.NEGATIVE), + LEVITATION("levitation", 25, Impact.NEGATIVE), + LUCK("luck", 26, Impact.POSITIVE), + UNLUCK("unluck", 27, Impact.NEGATIVE), + SLOW_FALLING("slow_falling", 28, Impact.POSITIVE), + CONDUIT_POWER("conduit_power", 29, Impact.POSITIVE), + DOLPHINS_GRACE("dolphins_grace", 30, Impact.POSITIVE), + BAD_OMEN("bad_omen", 31, Impact.NEGATIVE), + HERO_OF_THE_VILLAGE("hero_of_the_village", 32, Impact.POSITIVE); + + final String name; + final int id; + final Impact impact; + + StatusEffects(String name, int id, Impact impact) { + this.name = name; + this.id = id; + this.impact = impact; + } + + public static StatusEffects byId(int id) { + for (StatusEffects s : values()) { + if (s.getId() == id) { + return s; + } + } + return null; + } + + public static StatusEffects byName(String name) { + for (StatusEffects s : values()) { + if (s.getName().equals(name)) { + return s; + } + } + return null; + } + + public String getName() { + return name; + } + + public int getId() { + return id; + } + + public enum Impact { + POSITIVE, + NEGATIVE + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEntityEffect.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEntityEffect.java new file mode 100644 index 000000000..bf14e973e --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEntityEffect.java @@ -0,0 +1,56 @@ +/* + * 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.StatusEffect; +import de.bixilon.minosoft.game.datatypes.entities.StatusEffects; +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; + +public class PacketEntityEffect implements ClientboundPacket { + int entityId; + StatusEffect effect; + + + @Override + public void read(InPacketBuffer buffer, ProtocolVersion v) { + switch (v) { + case VERSION_1_7_10: + entityId = buffer.readInteger(); + effect = new StatusEffect(StatusEffects.byId(buffer.readByte()), buffer.readByte(), buffer.readShort()); + break; + } + } + + @Override + public void log() { + Log.game(String.format("Entity effect added: %d %s", entityId, effect.toString())); + } + + @Override + public void handle(PacketHandler h) { + h.handle(this); + } + + public int getEntityId() { + return entityId; + } + + public StatusEffect getEffect() { + return effect; + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketRemoveEntityEffect.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketRemoveEntityEffect.java new file mode 100644 index 000000000..c0873e707 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketRemoveEntityEffect.java @@ -0,0 +1,55 @@ +/* + * 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.StatusEffects; +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; + +public class PacketRemoveEntityEffect implements ClientboundPacket { + int entityId; + StatusEffects effect; + + + @Override + public void read(InPacketBuffer buffer, ProtocolVersion v) { + switch (v) { + case VERSION_1_7_10: + entityId = buffer.readInteger(); + effect = StatusEffects.byId(buffer.readByte()); + break; + } + } + + @Override + public void log() { + Log.game(String.format("Entity effect removed: %d %s", entityId, effect.name())); + } + + @Override + public void handle(PacketHandler h) { + h.handle(this); + } + + public int getEntityId() { + return entityId; + } + + public StatusEffects getEffect() { + return effect; + } +} 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 91af317be..51c786504 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -243,4 +243,12 @@ public class PacketHandler { public void handle(PacketChunkData pkg) { connection.getPlayer().getWorld().setChunk(pkg.getLocation(), pkg.getChunk()); } + + public void handle(PacketEntityEffect pkg) { + connection.getPlayer().getWorld().getEntity(pkg.getEntityId()).addEffect(pkg.getEffect()); + } + + public void handle(PacketRemoveEntityEffect pkg) { + connection.getPlayer().getWorld().getEntity(pkg.getEntityId()).removeEffect(pkg.getEffect()); + } } 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 ad0fe1843..6dc1355a5 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/Protocol.java @@ -26,14 +26,6 @@ import java.util.HashMap; public interface Protocol { HashMap> packetClassMapping = new HashMap<>(); - int getProtocolVersion(); - - int getPacketCommand(Packets.Serverbound p); - - String getName(); - - Packets.Clientbound getPacketByCommand(ConnectionState s, int command); - static Class getPacketByPacket(Packets.Clientbound p) { if (packetClassMapping.size() == 0) { // init @@ -82,5 +74,15 @@ public interface Protocol { packetClassMapping.put(Packets.Clientbound.PLAY_SPAWN_EXPERIENCE_ORB, PacketSpawnExperienceOrb.class); packetClassMapping.put(Packets.Clientbound.PLAY_SPAWN_WEATHER_ENTITY, PacketSpawnWeatherEntity.class); packetClassMapping.put(Packets.Clientbound.PLAY_CHUNK_DATA, PacketChunkData.class); + packetClassMapping.put(Packets.Clientbound.PLAY_ENTITY_EFFECT, PacketEntityEffect.class); + packetClassMapping.put(Packets.Clientbound.PLAY_REMOVE_ENTITY_EFFECT, PacketRemoveEntityEffect.class); } + + int getProtocolVersion(); + + int getPacketCommand(Packets.Serverbound p); + + String getName(); + + Packets.Clientbound getPacketByCommand(ConnectionState s, int command); } \ No newline at end of file