diff --git a/src/main/java/de/bixilon/minosoft/modding/event/EventListener.java b/src/main/java/de/bixilon/minosoft/modding/event/EventListener.java index 92e126882..08f556219 100644 --- a/src/main/java/de/bixilon/minosoft/modding/event/EventListener.java +++ b/src/main/java/de/bixilon/minosoft/modding/event/EventListener.java @@ -84,4 +84,16 @@ public class EventListener { public void onLightningBoltSpawn(LightningBoltSpawnEvent event) { } + + public void onMultiBlockChange(MultiBlockChangeEvent event) { + } + + public void onBlockEntityMetaDataChange(BlockEntityMetaDataChangeEvent event) { + } + + public void onChunkDataChange(ChunkDataChangeEvent event) { + } + + public void onEffect(EffectEvent event) { + } } diff --git a/src/main/java/de/bixilon/minosoft/modding/event/events/BlockEntityMetaDataChangeEvent.java b/src/main/java/de/bixilon/minosoft/modding/event/events/BlockEntityMetaDataChangeEvent.java new file mode 100644 index 000000000..4362afa40 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/modding/event/events/BlockEntityMetaDataChangeEvent.java @@ -0,0 +1,62 @@ +/* + * 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.modding.event.events; + +import de.bixilon.minosoft.game.datatypes.world.BlockPosition; +import de.bixilon.minosoft.modding.event.EventListener; +import de.bixilon.minosoft.protocol.network.Connection; +import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketBlockEntityMetadata; +import de.bixilon.minosoft.util.nbt.tag.CompoundTag; + +import javax.annotation.Nullable; + +public class BlockEntityMetaDataChangeEvent extends Event { + final BlockPosition position; + final PacketBlockEntityMetadata.BlockEntityActions action; + final CompoundTag nbt; + + public BlockEntityMetaDataChangeEvent(Connection connection, BlockPosition position, PacketBlockEntityMetadata.BlockEntityActions action, CompoundTag nbt) { + super(connection); + this.position = position; + this.action = action; + this.nbt = nbt; + this.nbt.setFinal(); + } + + public BlockEntityMetaDataChangeEvent(Connection connection, PacketBlockEntityMetadata pkg) { + super(connection); + this.position = pkg.getPosition(); + this.action = pkg.getAction(); + this.nbt = pkg.getNbt(); + this.nbt.setFinal(); + } + + public BlockPosition getPosition() { + return position; + } + + @Nullable + public PacketBlockEntityMetadata.BlockEntityActions getAction() { + return action; + } + + public CompoundTag getNbt() { + return nbt; + } + + @Override + public void handle(EventListener listener) { + listener.onBlockEntityMetaDataChange(this); + } +} diff --git a/src/main/java/de/bixilon/minosoft/modding/event/events/ChunkDataChangeEvent.java b/src/main/java/de/bixilon/minosoft/modding/event/events/ChunkDataChangeEvent.java new file mode 100644 index 000000000..0f6eb6d70 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/modding/event/events/ChunkDataChangeEvent.java @@ -0,0 +1,68 @@ +/* + * 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.modding.event.events; + +import de.bixilon.minosoft.game.datatypes.world.Chunk; +import de.bixilon.minosoft.game.datatypes.world.ChunkLocation; +import de.bixilon.minosoft.modding.event.EventListener; +import de.bixilon.minosoft.protocol.network.Connection; +import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketChunkData; +import de.bixilon.minosoft.util.nbt.tag.CompoundTag; + +/** + * Fired when a new chunk is received or a full chunk changes + */ +public class ChunkDataChangeEvent extends Event { + private final ChunkLocation location; + private final Chunk chunk; + private final CompoundTag heightMap; + + public ChunkDataChangeEvent(Connection connection, ChunkLocation location, Chunk chunk, CompoundTag heightMap) { + super(connection); + this.location = location; + this.chunk = chunk; + this.heightMap = heightMap; + } + + public ChunkDataChangeEvent(Connection connection, ChunkLocation location, Chunk chunk) { + super(connection); + this.location = location; + this.chunk = chunk; + this.heightMap = new CompoundTag(); + } + + public ChunkDataChangeEvent(Connection connection, PacketChunkData pkg) { + super(connection); + this.location = pkg.getLocation(); + this.chunk = pkg.getChunk(); + this.heightMap = pkg.getHeightMap(); + } + + public ChunkLocation getLocation() { + return location; + } + + public Chunk getChunk() { + return chunk; + } + + public CompoundTag getHeightMap() { + return heightMap; + } + + @Override + public void handle(EventListener listener) { + listener.onChunkDataChange(this); + } +} diff --git a/src/main/java/de/bixilon/minosoft/modding/event/events/EffectEvent.java b/src/main/java/de/bixilon/minosoft/modding/event/events/EffectEvent.java new file mode 100644 index 000000000..dd2b60413 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/modding/event/events/EffectEvent.java @@ -0,0 +1,63 @@ +/* + * 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.modding.event.events; + +import de.bixilon.minosoft.game.datatypes.world.BlockPosition; +import de.bixilon.minosoft.modding.event.EventListener; +import de.bixilon.minosoft.protocol.network.Connection; +import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketEffect; + +public class EffectEvent extends CancelableEvent { + final PacketEffect.EffectEffects effect; + final BlockPosition position; + final int data; + final boolean disableRelativeVolume; + + public EffectEvent(Connection connection, PacketEffect.EffectEffects effect, BlockPosition position, int data, boolean disableRelativeVolume) { + super(connection); + this.effect = effect; + this.position = position; + this.data = data; + this.disableRelativeVolume = disableRelativeVolume; + } + + public EffectEvent(Connection connection, PacketEffect pkg) { + super(connection); + this.effect = pkg.getEffect(); + this.position = pkg.getPosition(); + this.data = pkg.getData(); + this.disableRelativeVolume = pkg.isDisableRelativeVolume(); + } + + public PacketEffect.EffectEffects getEffect() { + return effect; + } + + public BlockPosition getPosition() { + return position; + } + + public int getData() { + return data; + } + + public boolean isDisableRelativeVolume() { + return disableRelativeVolume; + } + + @Override + public void handle(EventListener listener) { + listener.onEffect(this); + } +} diff --git a/src/main/java/de/bixilon/minosoft/modding/event/events/MultiBlockChangeEvent.java b/src/main/java/de/bixilon/minosoft/modding/event/events/MultiBlockChangeEvent.java new file mode 100644 index 000000000..e8b22f9e9 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/modding/event/events/MultiBlockChangeEvent.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.modding.event.events; + +import de.bixilon.minosoft.game.datatypes.objectLoader.blocks.Block; +import de.bixilon.minosoft.game.datatypes.world.ChunkLocation; +import de.bixilon.minosoft.game.datatypes.world.InChunkLocation; +import de.bixilon.minosoft.modding.event.EventListener; +import de.bixilon.minosoft.protocol.network.Connection; +import de.bixilon.minosoft.protocol.packets.clientbound.play.PacketMultiBlockChange; + +import java.util.HashMap; + +/** + * Fired when at least block is changed + */ +public class MultiBlockChangeEvent extends Event { + private final HashMap blocks; + private final ChunkLocation location; + + public MultiBlockChangeEvent(Connection connection, HashMap blocks, ChunkLocation location) { + super(connection); + this.blocks = blocks; + this.location = location; + } + + public MultiBlockChangeEvent(Connection connection, PacketMultiBlockChange pkg) { + super(connection); + this.blocks = pkg.getBlocks(); + this.location = pkg.getLocation(); + } + + public HashMap getBlocks() { + return blocks; + } + + public ChunkLocation getLocation() { + return location; + } + + @Override + public void handle(EventListener listener) { + listener.onMultiBlockChange(this); + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockEntityMetadata.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockEntityMetadata.java index 7a8241fde..2de2eea2d 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockEntityMetadata.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockEntityMetadata.java @@ -29,7 +29,6 @@ public class PacketBlockEntityMetadata implements ClientboundPacket { @Override public boolean read(InByteBuffer buffer) { - if (buffer.getProtocolId() < 6) { position = buffer.readBlockPositionShort(); action = BlockEntityActions.byId(buffer.readByte(), buffer.getProtocolId()); @@ -56,6 +55,10 @@ public class PacketBlockEntityMetadata implements ClientboundPacket { return position; } + public BlockEntityActions getAction() { + return action; + } + public CompoundTag getNbt() { return nbt; } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkBulk.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkBulk.java index 4dc7cf292..785c50346 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkBulk.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkBulk.java @@ -25,7 +25,7 @@ import de.bixilon.minosoft.util.Util; import java.util.HashMap; public class PacketChunkBulk implements ClientboundPacket { - final HashMap chunkMap = new HashMap<>(); + final HashMap chunks = new HashMap<>(); @Override public boolean read(InByteBuffer buffer) { @@ -49,7 +49,7 @@ public class PacketChunkBulk implements ClientboundPacket { short sectionBitMask = buffer.readShort(); short addBitMask = buffer.readShort(); - chunkMap.put(new ChunkLocation(x, z), ChunkUtil.readChunkPacket(decompressed, sectionBitMask, addBitMask, true, containsSkyLight)); + chunks.put(new ChunkLocation(x, z), ChunkUtil.readChunkPacket(decompressed, sectionBitMask, addBitMask, true, containsSkyLight)); } return true; } @@ -67,7 +67,7 @@ public class PacketChunkBulk implements ClientboundPacket { sectionBitMask[i] = buffer.readShort(); } for (int i = 0; i < chunkCount; i++) { - chunkMap.put(new ChunkLocation(x[i], z[i]), ChunkUtil.readChunkPacket(buffer, sectionBitMask[i], (short) 0, true, containsSkyLight)); + chunks.put(new ChunkLocation(x[i], z[i]), ChunkUtil.readChunkPacket(buffer, sectionBitMask[i], (short) 0, true, containsSkyLight)); } return true; } @@ -79,10 +79,10 @@ public class PacketChunkBulk implements ClientboundPacket { @Override public void log() { - Log.protocol(String.format("Chunk bulk packet received (chunks=%s)", chunkMap.size())); + Log.protocol(String.format("Chunk bulk packet received (chunks=%s)", chunks.size())); } - public HashMap getChunkMap() { - return chunkMap; + public HashMap getChunks() { + return chunks; } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEffect.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEffect.java index e6b6d9ed7..13fbcb008 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEffect.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketEffect.java @@ -22,11 +22,10 @@ import de.bixilon.minosoft.protocol.protocol.InByteBuffer; import de.bixilon.minosoft.protocol.protocol.PacketHandler; public class PacketEffect implements ClientboundPacket { - // is this class used??? What about PacketParticle or PacketSoundEffect? EffectEffects effect; BlockPosition position; int data; - boolean disableRelativeVolume; // normally only at MOB_ENDERDRAGON_END and MOB_WITHER_SPAWN, but we allow this everywhere + boolean disableRelativeVolume; @Override public boolean read(InByteBuffer buffer) { 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 07a6041d4..5caed8f9e 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/PacketHandler.java @@ -167,7 +167,9 @@ public class PacketHandler { } public void handle(PacketChunkBulk pkg) { - connection.getPlayer().getWorld().setChunks(pkg.getChunkMap()); + pkg.getChunks().forEach(((location, chunk) -> connection.fireEvent(new ChunkDataChangeEvent(connection, location, chunk)))); + + connection.getPlayer().getWorld().setChunks(pkg.getChunks()); } public void handle(PacketUpdateHealth pkg) { @@ -311,6 +313,7 @@ public class PacketHandler { Log.warn(String.format("Server tried to change blocks in unloaded chunks! (location=%s)", pkg.getLocation())); return; } + connection.fireEvent(new MultiBlockChangeEvent(connection, pkg)); chunk.setBlocks(pkg.getBlocks()); } @@ -343,6 +346,9 @@ public class PacketHandler { } public void handle(PacketChunkData pkg) { + pkg.getBlockEntities().forEach(((position, compoundTag) -> connection.fireEvent(new BlockEntityMetaDataChangeEvent(connection, position, null, compoundTag)))); + connection.fireEvent(new ChunkDataChangeEvent(connection, pkg)); + connection.getPlayer().getWorld().setChunk(pkg.getLocation(), pkg.getChunk()); connection.getPlayer().getWorld().setBlockEntityData(pkg.getBlockEntities()); } @@ -404,6 +410,7 @@ public class PacketHandler { } public void handle(PacketBlockEntityMetadata pkg) { + connection.fireEvent(new BlockEntityMetaDataChangeEvent(connection, pkg)); connection.getPlayer().getWorld().setBlockEntityData(pkg.getPosition(), pkg.getNbt()); } @@ -487,7 +494,9 @@ public class PacketHandler { } public void handle(PacketEffect pkg) { - // ToDo + if (connection.fireEvent(new EffectEvent(connection, pkg))) { + return; + } } public void handle(PacketScoreboardObjective pkg) { @@ -499,7 +508,6 @@ public class PacketHandler { } public void handle(PacketScoreboardUpdateScore pkg) { - // ToDo handle correctly switch (pkg.getAction()) { case CREATE_UPDATE -> connection.getPlayer().getScoreboardManager().getObjective(pkg.getScoreName()).addScore(new ScoreboardScore(pkg.getItemName(), pkg.getScoreName(), pkg.getScoreValue())); case REMOVE -> { @@ -547,7 +555,6 @@ public class PacketHandler { if (connection.fireEvent(event)) { return; } - // ToDo ask user, download pack. for now just send an okay } public void handle(PacketEntityProperties pkg) {