From 4f46f98c64eb3b9a92eb16957cd1de2866fdaebd Mon Sep 17 00:00:00 2001 From: Bixilon Date: Tue, 29 Dec 2020 16:48:54 +0100 Subject: [PATCH] wip: block tweaker --- .../minosoft/data/mappings/ModIdentifier.java | 12 +++-- .../minosoft/data/mappings/blocks/Block.java | 7 +++ .../data/mappings/tweaker/TweakBlocks.java | 12 +++++ .../{ => tweaker}/VersionTweaker.java | 53 ++++++++++++++++++- .../de/bixilon/minosoft/data/world/Chunk.java | 4 ++ .../data/world/InChunkSectionLocation.kt | 6 +++ .../clientbound/play/PacketBlockChange.java | 10 +++- .../clientbound/play/PacketChunkBulk.java | 3 ++ .../clientbound/play/PacketChunkData.java | 3 ++ .../play/PacketMultiBlockChange.java | 13 +++++ .../clientbound/play/PacketSpawnMob.java | 2 +- .../clientbound/play/PacketSpawnObject.java | 2 +- 12 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/data/mappings/tweaker/TweakBlocks.java rename src/main/java/de/bixilon/minosoft/data/mappings/{ => tweaker}/VersionTweaker.java (60%) diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/ModIdentifier.java b/src/main/java/de/bixilon/minosoft/data/mappings/ModIdentifier.java index 38db9db1b..8e1bfef47 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/ModIdentifier.java +++ b/src/main/java/de/bixilon/minosoft/data/mappings/ModIdentifier.java @@ -20,10 +20,12 @@ import java.util.Objects; public class ModIdentifier { protected final String mod; protected final String identifier; + public final String fullIdentifier; public ModIdentifier(String mod, String identifier) { this.mod = mod; this.identifier = identifier; + this.fullIdentifier = mod + ":" + identifier; } public ModIdentifier(String fullIdentifier) { @@ -31,15 +33,17 @@ public class ModIdentifier { if (split.length == 1) { this.mod = ProtocolDefinition.DEFAULT_MOD; this.identifier = fullIdentifier; - return; + } else { + this.mod = split[0]; + this.identifier = split[1]; } - this.mod = split[0]; - this.identifier = split[1]; + this.fullIdentifier = this.mod + ":" + this.identifier; } public ModIdentifier(ModIdentifier identifier) { this.mod = identifier.getMod(); this.identifier = identifier.getIdentifier(); + this.fullIdentifier = identifier.getFullIdentifier(); } public static ModIdentifier getIdentifier(String identifier) throws IllegalArgumentException { @@ -60,7 +64,7 @@ public class ModIdentifier { } public String getFullIdentifier() { - return String.format("%s:%s", this.mod, this.identifier); + return this.fullIdentifier; } @Override diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.java b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.java index e68637e08..5f70f408c 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.java +++ b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.java @@ -15,6 +15,7 @@ package de.bixilon.minosoft.data.mappings.blocks; import de.bixilon.minosoft.data.mappings.ModIdentifier; +import java.util.Arrays; import java.util.HashSet; import java.util.Objects; @@ -34,6 +35,12 @@ public class Block extends ModIdentifier { this.rotation = BlockRotations.NONE; } + public Block(String fullIdentifier, BlockProperties... properties) { + super(fullIdentifier); + this.properties = new HashSet<>(Arrays.asList(properties)); + this.rotation = BlockRotations.NONE; + } + public Block(String mod, String identifier, BlockRotations rotation) { super(mod, identifier); this.properties = new HashSet<>(); diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/TweakBlocks.java b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/TweakBlocks.java new file mode 100644 index 000000000..df6e63301 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/TweakBlocks.java @@ -0,0 +1,12 @@ +package de.bixilon.minosoft.data.mappings.tweaker; + +import de.bixilon.minosoft.data.mappings.blocks.Block; +import de.bixilon.minosoft.data.mappings.blocks.BlockProperties; + +public final class TweakBlocks { + public static final Block GRASS_BLOCK_SNOWY_YES = new Block("grass", BlockProperties.GRASS_SNOWY_YES); + public static final Block GRASS_BLOCK_SNOWY_NO = new Block("grass", BlockProperties.GRASS_SNOWY_NO); + public static final Block SNOW = new Block("snow"); + public static final Block SNOW_LAYER = new Block("snow_layer"); + +} diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/VersionTweaker.java b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.java similarity index 60% rename from src/main/java/de/bixilon/minosoft/data/mappings/VersionTweaker.java rename to src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.java index 322772723..7eb160bd8 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/VersionTweaker.java +++ b/src/main/java/de/bixilon/minosoft/data/mappings/tweaker/VersionTweaker.java @@ -11,7 +11,7 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.data.mappings; +package de.bixilon.minosoft.data.mappings.tweaker; import de.bixilon.minosoft.data.entities.EntityMetaData; import de.bixilon.minosoft.data.entities.EntityMetaDataFields; @@ -19,6 +19,14 @@ import de.bixilon.minosoft.data.entities.entities.Entity; import de.bixilon.minosoft.data.entities.entities.animal.horse.*; import de.bixilon.minosoft.data.entities.entities.monster.*; import de.bixilon.minosoft.data.entities.entities.vehicle.*; +import de.bixilon.minosoft.data.mappings.blocks.Block; +import de.bixilon.minosoft.data.world.Chunk; +import de.bixilon.minosoft.data.world.ChunkSection; +import de.bixilon.minosoft.data.world.InChunkLocation; +import de.bixilon.minosoft.data.world.InChunkSectionLocation; +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; + +import java.util.Map; import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_1_8_9; @@ -81,4 +89,47 @@ public class VersionTweaker { } return fakeClass; } + + public static Chunk transformChunk(Chunk chunk, int versionId) { + // some blocks need to be tweaked. eg. Grass with a snow block on top becomes snowy grass block + if (versionId >= ProtocolDefinition.FLATTING_VERSION_ID) { + return chunk; + } + for (Map.Entry sectionEntry : chunk.getSections().entrySet()) { + for (Map.Entry blockEntry : sectionEntry.getValue().getBlocks().entrySet()) { + Block newBlock = transformBlock(blockEntry.getValue(), chunk, blockEntry.getKey(), sectionEntry.getKey()); + if (newBlock == blockEntry.getValue()) { + continue; + } + sectionEntry.getValue().setBlock(blockEntry.getKey(), newBlock); + } + } + return chunk; + } + + public static Block transformBlock(Block originalBlock, Chunk chunk, InChunkLocation location) { + return transformBlock(originalBlock, chunk, location.getInChunkSectionLocation(), (byte) (location.getY() / ProtocolDefinition.SECTION_HEIGHT_Y)); + } + + public static Block transformBlock(Block originalBlock, Chunk chunk, InChunkSectionLocation location, byte sectionHeight) { + switch (originalBlock.getFullIdentifier()) { + case "minecraft:grass" -> { + Block above = getBlockAbove(chunk, location, sectionHeight); + if (above == null) { + break; + } + if (above.equals(TweakBlocks.SNOW) || above.equals(TweakBlocks.SNOW_LAYER)) { + return TweakBlocks.GRASS_BLOCK_SNOWY_YES; + } else { + return TweakBlocks.GRASS_BLOCK_SNOWY_NO; + } + } + // ToDo: all blocks. e.g. doors, etc + } + return originalBlock; + } + + private static Block getBlockAbove(Chunk chunk, InChunkSectionLocation location, byte sectionHeight) { + return chunk.getBlock(location.getInChunkLocation(sectionHeight)); + } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/Chunk.java b/src/main/java/de/bixilon/minosoft/data/world/Chunk.java index aece41d62..3810b0e9a 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/Chunk.java +++ b/src/main/java/de/bixilon/minosoft/data/world/Chunk.java @@ -82,4 +82,8 @@ public class Chunk { public void setBlockEntityData(HashMap blockEntities) { blockEntities.forEach(this::setBlockEntityData); } + + public HashMap getSections() { + return this.sections; + } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionLocation.kt b/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionLocation.kt index 1cc702255..c1beb5246 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionLocation.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/InChunkSectionLocation.kt @@ -12,6 +12,8 @@ */ package de.bixilon.minosoft.data.world +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition + /** * Chunk X, Y and Z location (max 16x16x16) */ @@ -20,4 +22,8 @@ data class InChunkSectionLocation(val x: Int, val y: Int, val z: Int) { override fun toString(): String { return "($x $y $z)" } + + fun getInChunkLocation(sectionHeight: Byte): InChunkLocation { + return InChunkLocation(x, y + ProtocolDefinition.SECTION_HEIGHT_Y * sectionHeight, z) + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java index 9c83c3daf..263f60345 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketBlockChange.java @@ -14,6 +14,7 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play; import de.bixilon.minosoft.data.mappings.blocks.Block; +import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker; import de.bixilon.minosoft.data.world.BlockPosition; import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.logging.Log; @@ -50,7 +51,14 @@ public class PacketBlockChange extends ClientboundPacket { } connection.fireEvent(new BlockChangeEvent(connection, this)); - chunk.setBlock(getPosition().getInChunkLocation(), getBlock()); + + // tweak + if (!connection.getVersion().isFlattened()) { + Block block = VersionTweaker.transformBlock(getBlock(), chunk, getPosition().getInChunkLocation()); + chunk.setBlock(getPosition().getInChunkLocation(), block); + } else { + chunk.setBlock(getPosition().getInChunkLocation(), getBlock()); + } } @Override 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 268eab6a7..04dd3ddfb 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 @@ -13,6 +13,7 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play; +import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker; import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.data.world.ChunkLocation; import de.bixilon.minosoft.logging.Log; @@ -78,6 +79,8 @@ public class PacketChunkBulk extends ClientboundPacket { @Override public void handle(Connection connection) { + this.chunks.values().forEach((chunk) -> VersionTweaker.transformChunk(chunk, connection.getVersion().getVersionId())); + getChunks().forEach(((location, chunk) -> connection.fireEvent(new ChunkDataChangeEvent(connection, location, chunk)))); connection.getPlayer().getWorld().setChunks(getChunks()); diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java index 25c0b1931..dc51844e8 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketChunkData.java @@ -14,6 +14,7 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play; import de.bixilon.minosoft.data.entities.block.BlockEntityMetaData; +import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker; import de.bixilon.minosoft.data.world.BlockPosition; import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.data.world.ChunkLocation; @@ -114,6 +115,8 @@ public class PacketChunkData extends ClientboundPacket { @Override public void handle(Connection connection) { getBlockEntities().forEach(((position, compoundTag) -> connection.fireEvent(new BlockEntityMetaDataChangeEvent(connection, position, null, compoundTag)))); + VersionTweaker.transformChunk(this.chunk, connection.getVersion().getVersionId()); + connection.fireEvent(new ChunkDataChangeEvent(connection, this)); connection.getPlayer().getWorld().setChunk(getLocation(), getChunk()); diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java index 7152b03d8..e67ec932a 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketMultiBlockChange.java @@ -14,6 +14,7 @@ package de.bixilon.minosoft.protocol.packets.clientbound.play; import de.bixilon.minosoft.data.mappings.blocks.Block; +import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker; import de.bixilon.minosoft.data.world.Chunk; import de.bixilon.minosoft.data.world.ChunkLocation; import de.bixilon.minosoft.data.world.InChunkLocation; @@ -24,6 +25,7 @@ import de.bixilon.minosoft.protocol.packets.ClientboundPacket; import de.bixilon.minosoft.protocol.protocol.InByteBuffer; import java.util.HashMap; +import java.util.Map; import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*; @@ -86,6 +88,17 @@ public class PacketMultiBlockChange extends ClientboundPacket { } connection.fireEvent(new MultiBlockChangeEvent(connection, this)); chunk.setBlocks(getBlocks()); + + // tweak + if (!connection.getVersion().isFlattened()) { + for (Map.Entry entry : getBlocks().entrySet()) { + Block block = VersionTweaker.transformBlock(entry.getValue(), chunk, entry.getKey()); + if (block == entry.getValue()) { + continue; + } + chunk.setBlock(entry.getKey(), block); + } + } } @Override 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 index be7aac180..b6e07556a 100644 --- 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 @@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.entities.Location; import de.bixilon.minosoft.data.entities.Velocity; import de.bixilon.minosoft.data.entities.entities.Entity; import de.bixilon.minosoft.data.entities.entities.UnknownEntityException; -import de.bixilon.minosoft.data.mappings.VersionTweaker; +import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.modding.event.events.EntitySpawnEvent; import de.bixilon.minosoft.protocol.network.Connection; diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnObject.java b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnObject.java index 53b462287..fc2767f4d 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnObject.java +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketSpawnObject.java @@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.entities.Objects; import de.bixilon.minosoft.data.entities.Velocity; import de.bixilon.minosoft.data.entities.entities.Entity; import de.bixilon.minosoft.data.entities.entities.UnknownEntityException; -import de.bixilon.minosoft.data.mappings.VersionTweaker; +import de.bixilon.minosoft.data.mappings.tweaker.VersionTweaker; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.modding.event.events.EntitySpawnEvent; import de.bixilon.minosoft.protocol.network.Connection;