From b1aeba61c0f1623f31f46fc51c088038f5330c1c Mon Sep 17 00:00:00 2001 From: Paul Fulham Date: Fri, 20 Nov 2020 23:03:13 -0800 Subject: [PATCH 01/11] Add network direction designation --- .../foundation/networking/AllPackets.java | 70 ++++++++++--------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index 8feb79656..f7c6ed4af 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -25,8 +25,8 @@ import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket; import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket; import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; import com.simibubi.create.content.schematics.packet.SchematicPlacePacket; -import com.simibubi.create.content.schematics.packet.SchematicUploadPacket; import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; +import com.simibubi.create.content.schematics.packet.SchematicUploadPacket; import com.simibubi.create.foundation.command.ConfigureConfigPacket; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; @@ -36,44 +36,48 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.network.NetworkDirection; import net.minecraftforge.fml.network.NetworkEvent.Context; import net.minecraftforge.fml.network.NetworkRegistry; import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor.TargetPoint; import net.minecraftforge.fml.network.simple.SimpleChannel; +import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_SERVER; +import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT; + public enum AllPackets { // Client to Server - NBT(NbtPacket.class, NbtPacket::new), - CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new), - CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new), - CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new), - CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new), - PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new), - UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new), - CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new), - CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new), - CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new), - EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new), - CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new), - CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new), - PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new), - MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new), - INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new), - SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new), + NBT(NbtPacket.class, NbtPacket::new, PLAY_TO_SERVER), + CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new, PLAY_TO_SERVER), + CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new, PLAY_TO_SERVER), + CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new, PLAY_TO_SERVER), + CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new, PLAY_TO_SERVER), + PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER), + UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER), + CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER), + CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new, PLAY_TO_SERVER), + CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new, PLAY_TO_SERVER), + EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new, PLAY_TO_SERVER), + CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new, PLAY_TO_SERVER), + CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new, PLAY_TO_SERVER), + PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new, PLAY_TO_SERVER), + MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new, PLAY_TO_SERVER), + INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new, PLAY_TO_SERVER), + SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new, PLAY_TO_SERVER), // Server to Client - SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new), - SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new), - BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new), - CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new), - CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new), - GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new), - CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new), - LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new), - MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new), - FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new), + SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), + SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT), + BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT), + CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT), + GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new, PLAY_TO_CLIENT), + LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new, PLAY_TO_CLIENT), + MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new, PLAY_TO_CLIENT), + FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT), ; @@ -83,8 +87,8 @@ public enum AllPackets { private LoadedPacket packet; - private AllPackets(Class type, Function factory) { - packet = new LoadedPacket<>(type, factory); + private AllPackets(Class type, Function factory, NetworkDirection direction) { + packet = new LoadedPacket<>(type, factory, direction); } public static void registerPackets() { @@ -110,16 +114,18 @@ public enum AllPackets { Function decoder; BiConsumer> handler; Class type; + NetworkDirection direction; - private LoadedPacket(Class type, Function factory) { + private LoadedPacket(Class type, Function factory, NetworkDirection direction) { encoder = T::write; decoder = factory; handler = T::handle; this.type = type; + this.direction = direction; } private void register() { - channel.messageBuilder(type, index++) + channel.messageBuilder(type, index++, direction) .encoder(encoder) .decoder(decoder) .consumer(handler) From e1d1b062f8fc5b18f3ae83b381396a3970304953 Mon Sep 17 00:00:00 2001 From: Paul Fulham Date: Sat, 21 Nov 2020 18:20:49 -0800 Subject: [PATCH 02/11] Enforce network version --- .../com/simibubi/create/foundation/networking/AllPackets.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index f7c6ed4af..8bb4a5f83 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -93,8 +93,8 @@ public enum AllPackets { public static void registerPackets() { channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME) - .serverAcceptedVersions(s -> true) - .clientAcceptedVersions(s -> true) + .serverAcceptedVersions(NETWORK_VERSION::equals) + .clientAcceptedVersions(NETWORK_VERSION::equals) .networkProtocolVersion(() -> NETWORK_VERSION) .simpleChannel(); for (AllPackets packet : values()) From 7c8bd28421040a783e2637df083a86c63bc326cd Mon Sep 17 00:00:00 2001 From: Paul Fulham Date: Sat, 21 Nov 2020 18:28:05 -0800 Subject: [PATCH 03/11] Restrict schematicannon configuration --- .../packet/ConfigureSchematicannonPacket.java | 35 +++++-------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/ConfigureSchematicannonPacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/ConfigureSchematicannonPacket.java index 4a5984e77..2e66fc255 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/ConfigureSchematicannonPacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/ConfigureSchematicannonPacket.java @@ -2,15 +2,13 @@ package com.simibubi.create.content.schematics.packet; import java.util.function.Supplier; +import com.simibubi.create.content.schematics.block.SchematicannonContainer; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity.State; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkEvent.Context; public class ConfigureSchematicannonPacket extends SimplePacketBase { @@ -21,45 +19,28 @@ public class ConfigureSchematicannonPacket extends SimplePacketBase { private Option option; private boolean set; - private BlockPos pos; - public static ConfigureSchematicannonPacket setOption(BlockPos pos, Option option, boolean set) { - ConfigureSchematicannonPacket packet = new ConfigureSchematicannonPacket(pos); - packet.option = option; - packet.set = set; - return packet; - } - - public ConfigureSchematicannonPacket(BlockPos pos) { - this.pos = pos; + public ConfigureSchematicannonPacket(Option option, boolean set) { + this.option = option; + this.set = set; } public ConfigureSchematicannonPacket(PacketBuffer buffer) { - pos = buffer.readBlockPos(); - option = Option.values()[buffer.readInt()]; - set = buffer.readBoolean(); + this(buffer.readEnumValue(Option.class), buffer.readBoolean()); } public void write(PacketBuffer buffer) { - buffer.writeBlockPos(pos); - buffer.writeInt(option.ordinal()); + buffer.writeEnumValue(option); buffer.writeBoolean(set); } public void handle(Supplier context) { context.get().enqueueWork(() -> { ServerPlayerEntity player = context.get().getSender(); - if (player == null) - return; - World world = player.world; - if (world == null || !world.isBlockPresent(pos)) + if (player == null || !(player.openContainer instanceof SchematicannonContainer)) return; - TileEntity tileEntity = world.getTileEntity(pos); - if (!(tileEntity instanceof SchematicannonTileEntity)) - return; - - SchematicannonTileEntity te = (SchematicannonTileEntity) tileEntity; + SchematicannonTileEntity te = ((SchematicannonContainer) player.openContainer).getTileEntity(); switch (option) { case DONT_REPLACE: case REPLACE_ANY: From fe8c3d4e73360aa48d75a51677ee393af13fd2e1 Mon Sep 17 00:00:00 2001 From: Paul Fulham Date: Sat, 21 Nov 2020 19:28:54 -0800 Subject: [PATCH 04/11] Add nbt privilege checks --- .../schematics/SchematicProcessor.java | 59 +++++++++++++++++++ .../schematics/item/SchematicItem.java | 2 + 2 files changed, 61 insertions(+) create mode 100644 src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java new file mode 100644 index 000000000..f6d1a61d3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.schematics; + +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.types.DynamicOps; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorldReader; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.template.IStructureProcessorType; +import net.minecraft.world.gen.feature.template.PlacementSettings; +import net.minecraft.world.gen.feature.template.StructureProcessor; +import net.minecraft.world.gen.feature.template.Template; + +import javax.annotation.Nullable; +import java.util.Optional; + +public class SchematicProcessor extends StructureProcessor { + public static final SchematicProcessor INSTANCE = new SchematicProcessor(); + + @Nullable + @Override + public Template.BlockInfo process(IWorldReader world, BlockPos pos, Template.BlockInfo rawInfo, Template.BlockInfo info, PlacementSettings settings, @Nullable Template template) { + if (info.nbt != null) { + TileEntity te = info.state.createTileEntity(world); + if (te != null && te.onlyOpsCanSetNbt()) { + return new Template.BlockInfo(info.pos, info.state, null); + } + } + return info; + } + + @Nullable + @Override + public Template.EntityInfo processEntity(IWorldReader world, BlockPos pos, Template.EntityInfo rawInfo, Template.EntityInfo info, PlacementSettings settings, Template template) { + return EntityType.readEntityType(info.nbt) + .flatMap(type -> { + if (world instanceof World) { + Entity e = type.create((World) world); + if (e != null && !e.ignoreItemEntityData()) { + return Optional.of(info); + } + } + return Optional.empty(); + }) + .orElse(null); + } + + @Override + protected IStructureProcessorType getType() { + return dynamic -> INSTANCE; + } + + @Override + protected Dynamic serialize0(DynamicOps ops) { + return new Dynamic<>(ops, ops.emptyMap()); + } +} diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java index 2ddf14b10..ac7771002 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java @@ -12,6 +12,7 @@ import javax.annotation.Nonnull; import org.apache.commons.io.IOUtils; import com.simibubi.create.AllItems; +import com.simibubi.create.content.schematics.SchematicProcessor; import com.simibubi.create.content.schematics.client.SchematicEditScreen; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.utility.Lang; @@ -94,6 +95,7 @@ public class SchematicItem extends Item { PlacementSettings settings = new PlacementSettings(); settings.setRotation(Rotation.valueOf(tag.getString("Rotation"))); settings.setMirror(Mirror.valueOf(tag.getString("Mirror"))); + settings.addProcessor(SchematicProcessor.INSTANCE); return settings; } From 6e131583dd39bf5e7359c4de031261a240ce15c0 Mon Sep 17 00:00:00 2001 From: Paul Fulham Date: Sat, 21 Nov 2020 21:19:38 -0800 Subject: [PATCH 05/11] Fix path handling --- .../schematics/ServerSchematicLoader.java | 79 ++++++++++--------- .../schematics/item/SchematicItem.java | 38 +++++---- .../foundation/utility/FilesHelper.java | 15 +--- 3 files changed, 67 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java index 8c8e117fa..5c2ee7466 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java @@ -91,10 +91,8 @@ public class ServerSchematicLoader { } public void handleNewUpload(ServerPlayerEntity player, String schematic, long size, BlockPos pos) { - String playerPath = getSchematicPath() + "/" + player.getName() - .getFormattedText(); - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName(); + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; FilesHelper.createFolderIfMissing(playerPath); // Unsupported Format @@ -103,6 +101,14 @@ public class ServerSchematicLoader { return; } + Path schematicPath = Paths.get(getSchematicPath()).toAbsolutePath(); + + Path uploadPath = schematicPath.resolve(playerSchematicId).normalize(); + if (!uploadPath.startsWith(schematicPath)) { + Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); + return; + } + // Too big if (!validateSchematicSizeOnServer(player, size)) return; @@ -117,12 +123,13 @@ public class ServerSchematicLoader { if (table == null) return; - // Delete schematic with same name - Files.deleteIfExists(Paths.get(getSchematicPath(), playerSchematicId)); - // Too many Schematics - Stream list = Files.list(Paths.get(playerPath)); - if (list.count() >= getConfig().maxSchematics.get()) { + long count; + try (Stream list = Files.list(Paths.get(playerPath))) { + count = list.count(); + } + + if (count >= getConfig().maxSchematics.get()) { Stream list2 = Files.list(Paths.get(playerPath)); Optional lastFilePath = list2.filter(f -> !Files.isDirectory(f)) .min(Comparator.comparingLong(f -> f.toFile() @@ -132,11 +139,9 @@ public class ServerSchematicLoader { Files.deleteIfExists(lastFilePath.get()); } } - list.close(); // Open Stream - OutputStream writer = - Files.newOutputStream(Paths.get(getSchematicPath(), playerSchematicId), StandardOpenOption.CREATE_NEW); + OutputStream writer = Files.newOutputStream(uploadPath); activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, player.getServerWorld(), pos)); // Notify Tile Entity @@ -165,8 +170,7 @@ public class ServerSchematicLoader { } public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) { - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; if (activeUploads.containsKey(playerSchematicId)) { SchematicUploadEntry entry = activeUploads.get(playerSchematicId); @@ -236,8 +240,7 @@ public class ServerSchematicLoader { } public void handleFinishedUpload(ServerPlayerEntity player, String schematic) { - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; if (activeUploads.containsKey(playerSchematicId)) { try { @@ -258,8 +261,7 @@ public class ServerSchematicLoader { if (table == null) return; table.finishUpload(); - table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getName() - .getFormattedText())); + table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getGameProfile().getName())); } catch (IOException e) { Create.logger.error("Exception Thrown when finishing Upload: " + playerSchematicId); @@ -270,15 +272,21 @@ public class ServerSchematicLoader { public void handleInstantSchematic(ServerPlayerEntity player, String schematic, World world, BlockPos pos, BlockPos bounds) { - String playerPath = getSchematicPath() + "/" + player.getName() - .getFormattedText(); - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName(); + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; FilesHelper.createFolderIfMissing(playerPath); // Unsupported Format if (!schematic.endsWith(".nbt")) { - Create.logger.warn("Attempted Schematic Upload with non-supported Format: " + playerSchematicId); + Create.logger.warn("Attempted Schematic Upload with non-supported Format: {}", playerSchematicId); + return; + } + + Path schematicPath = Paths.get(getSchematicPath()).toAbsolutePath(); + + Path path = schematicPath.resolve(playerSchematicId).normalize(); + if (!path.startsWith(schematicPath)) { + Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); return; } @@ -287,39 +295,32 @@ public class ServerSchematicLoader { return; try { - // Delete schematic with same name - Path path = Paths.get(getSchematicPath(), playerSchematicId); - Files.deleteIfExists(path); - // Too many Schematics - Stream list = Files.list(Paths.get(playerPath)); - if (list.count() >= getConfig().maxSchematics.get()) { + long count; + try (Stream list = Files.list(Paths.get(playerPath))) { + count = list.count(); + } + + if (count >= getConfig().maxSchematics.get()) { Stream list2 = Files.list(Paths.get(playerPath)); Optional lastFilePath = list2.filter(f -> !Files.isDirectory(f)) .min(Comparator.comparingLong(f -> f.toFile() .lastModified())); list2.close(); - if (lastFilePath.isPresent()) + if (lastFilePath.isPresent()) Files.deleteIfExists(lastFilePath.get()); } - list.close(); Template t = new Template(); t.takeBlocksFromWorld(world, pos, bounds, true, Blocks.AIR); - OutputStream outputStream = null; - try { - outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE); + try (OutputStream outputStream = Files.newOutputStream(path)) { CompoundNBT nbttagcompound = t.writeToNBT(new CompoundNBT()); CompressedStreamTools.writeCompressed(nbttagcompound, outputStream); - player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getName() - .getFormattedText())); + player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getGameProfile().getName())); } catch (IOException e) { e.printStackTrace(); - } finally { - if (outputStream != null) - IOUtils.closeQuietly(outputStream); } } catch (IOException e) { Create.logger.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId); diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java index ac7771002..a07437758 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java @@ -3,13 +3,15 @@ package com.simibubi.create.content.schematics.item; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.List; import javax.annotation.Nonnull; -import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import com.simibubi.create.AllItems; import com.simibubi.create.content.schematics.SchematicProcessor; @@ -46,6 +48,8 @@ import net.minecraftforge.fml.common.thread.SidedThreadGroups; public class SchematicItem extends Item { + private static final Logger LOGGER = LogManager.getLogger(); + public SchematicItem(Properties properties) { super(properties.maxStackSize(1)); } @@ -106,25 +110,29 @@ public class SchematicItem extends Item { String schematic = blueprint.getTag() .getString("File"); - String filepath = ""; + if (!schematic.endsWith(".nbt")) + return t; - if (Thread.currentThread() - .getThreadGroup() == SidedThreadGroups.SERVER) - filepath = "schematics/uploaded/" + owner + "/" + schematic; - else - filepath = "schematics/" + schematic; + Path dir; + Path file; - InputStream stream = null; - try { - stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ); + if (Thread.currentThread().getThreadGroup() == SidedThreadGroups.SERVER) { + dir = Paths.get("schematics", "uploaded").toAbsolutePath(); + file = Paths.get(owner, schematic); + } else { + dir = Paths.get("schematics").toAbsolutePath(); + file = Paths.get(schematic); + } + + Path path = dir.resolve(file).normalize(); + if (!path.startsWith(dir)) + return t; + + try (InputStream stream = Files.newInputStream(path, StandardOpenOption.READ)) { CompoundNBT nbt = CompressedStreamTools.readCompressed(stream); t.read(nbt); - } catch (IOException e) { - // Player/Server doesnt have schematic saved - } finally { - if (stream != null) - IOUtils.closeQuietly(stream); + LOGGER.warn("Failed to read schematic", e); } return t; diff --git a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java index 67bc3f1fa..e59a45521 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java @@ -21,17 +21,10 @@ import net.minecraft.nbt.CompoundNBT; public class FilesHelper { public static void createFolderIfMissing(String name) { - Path path = Paths.get(name); - if (path.getParent() != null) - createFolderIfMissing(path.getParent() - .toString()); - - if (!Files.isDirectory(path)) { - try { - Files.createDirectory(path); - } catch (IOException e) { - Create.logger.warn("Could not create Folder: " + name); - } + try { + Files.createDirectories(Paths.get(name)); + } catch (IOException e) { + Create.logger.warn("Could not create Folder: {}", name); } } From 18b768b32f3703f14ea22ed509c014332736fa1a Mon Sep 17 00:00:00 2001 From: Paul Fulham Date: Sat, 21 Nov 2020 22:00:05 -0800 Subject: [PATCH 06/11] Fix upload handling --- .../content/schematics/ServerSchematicLoader.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java index 5c2ee7466..743cc5a3b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java @@ -101,10 +101,10 @@ public class ServerSchematicLoader { return; } - Path schematicPath = Paths.get(getSchematicPath()).toAbsolutePath(); + Path playerSchematicsPath = Paths.get(getSchematicPath(), player.getGameProfile().getName()).toAbsolutePath(); - Path uploadPath = schematicPath.resolve(playerSchematicId).normalize(); - if (!uploadPath.startsWith(schematicPath)) { + Path uploadPath = playerSchematicsPath.resolve(schematic).normalize(); + if (!uploadPath.startsWith(playerSchematicsPath)) { Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); return; } @@ -123,6 +123,9 @@ public class ServerSchematicLoader { if (table == null) return; + // Delete schematic with same name + Files.deleteIfExists(uploadPath); + // Too many Schematics long count; try (Stream list = Files.list(Paths.get(playerPath))) { @@ -295,6 +298,9 @@ public class ServerSchematicLoader { return; try { + // Delete schematic with same name + Files.deleteIfExists(path); + // Too many Schematics long count; try (Stream list = Files.list(Paths.get(playerPath))) { From bc6513a098f3fb2007f365f23c9f222e5aef93c4 Mon Sep 17 00:00:00 2001 From: Paul Fulham Date: Sat, 21 Nov 2020 22:13:50 -0800 Subject: [PATCH 07/11] Limit schematic memory usage --- .../create/content/schematics/item/SchematicItem.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java index a07437758..1bef9185f 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java @@ -1,12 +1,14 @@ package com.simibubi.create.content.schematics.item; +import java.io.BufferedInputStream; +import java.io.DataInputStream; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.List; +import java.util.zip.GZIPInputStream; import javax.annotation.Nonnull; @@ -27,6 +29,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTSizeTracker; import net.minecraft.nbt.NBTUtil; import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResultType; @@ -128,8 +131,9 @@ public class SchematicItem extends Item { if (!path.startsWith(dir)) return t; - try (InputStream stream = Files.newInputStream(path, StandardOpenOption.READ)) { - CompoundNBT nbt = CompressedStreamTools.readCompressed(stream); + try (DataInputStream stream = new DataInputStream(new BufferedInputStream( + new GZIPInputStream(Files.newInputStream(path, StandardOpenOption.READ))))) { + CompoundNBT nbt = CompressedStreamTools.read(stream, new NBTSizeTracker(0x20000000L)); t.read(nbt); } catch (IOException e) { LOGGER.warn("Failed to read schematic", e); From c5447d5b9cea85f32013bcd1f111dd5a983286c4 Mon Sep 17 00:00:00 2001 From: Snownee Date: Sun, 31 Jan 2021 14:56:46 +0800 Subject: [PATCH 08/11] Add NBTProcessors to enable detailed control to tile data. Add safe check when contraption blocks adding back to world --- .../data/create/tags/blocks/safe_nbt.json | 3 +- .../java/com/simibubi/create/AllTags.java | 2 + .../category/MechanicalCraftingCategory.java | 1 - .../components/fan/EncasedFanBlock.java | 1 - .../structureMovement/Contraption.java | 6 +- .../fluids/actors/SpoutTileEntity.java | 2 - .../curiosities/zapper/ZapperItem.java | 22 ++++--- .../zapper/blockzapper/BlockzapperItem.java | 2 +- .../zapper/terrainzapper/TerrainTools.java | 8 +-- .../block/redstone/RedstoneLinkBlock.java | 1 - .../schematics/SchematicProcessor.java | 9 ++- .../schematics/ServerSchematicLoader.java | 3 - .../block/SchematicannonTileEntity.java | 4 +- .../schematics/item/SchematicItem.java | 2 +- .../packet/SchematicPlacePacket.java | 3 + .../foundation/utility/FilesHelper.java | 1 - .../foundation/utility/NBTProcessors.java | 57 +++++++++++++++++++ 17 files changed, 98 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java diff --git a/src/generated/resources/data/create/tags/blocks/safe_nbt.json b/src/generated/resources/data/create/tags/blocks/safe_nbt.json index 78c06756f..d834c9f41 100644 --- a/src/generated/resources/data/create/tags/blocks/safe_nbt.json +++ b/src/generated/resources/data/create/tags/blocks/safe_nbt.json @@ -23,6 +23,7 @@ "create:redstone_link", "create:analog_lever", "create:adjustable_repeater", - "create:adjustable_pulse_repeater" + "create:adjustable_pulse_repeater", + "#minecraft:signs" ] } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index fb7675b88..71bf7c9d2 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -187,5 +187,7 @@ public class AllTags { AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS); AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE); + + AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS); } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java index ee3d7c168..db01bbd08 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MechanicalCraftingCategory.java @@ -8,7 +8,6 @@ import java.util.stream.Collectors; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllBlocks; import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter; -import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.foundation.gui.AllGuiTextures; import mezz.jei.api.constants.VanillaTypes; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java index 27e3107b7..5d8a6faa4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java @@ -1,6 +1,5 @@ package com.simibubi.create.content.contraptions.components.fan; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index bf4a6124f..4f8ae92c3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -48,6 +48,7 @@ import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; @@ -797,6 +798,8 @@ public abstract class Contraption { TileEntity tileEntity = world.getTileEntity(targetPos); CompoundNBT tag = block.nbt; + if (tileEntity != null) + tag = NBTProcessors.process(tileEntity, tag, false); if (tileEntity != null && tag != null) { tag.putInt("x", targetPos.getX()); tag.putInt("y", targetPos.getY()); @@ -828,7 +831,8 @@ public abstract class Contraption { } for (BlockInfo block : blocks.values()) { BlockPos targetPos = transform.apply(block.pos); - world.markAndNotifyBlock(targetPos, null, block.state, block.state, BlockFlags.IS_MOVING | BlockFlags.DEFAULT); + BlockState state = world.getBlockState(targetPos); + world.markAndNotifyBlock(targetPos, null, state, state, BlockFlags.IS_MOVING | BlockFlags.DEFAULT); } for (int i = 0; i < inventory.getSlots(); i++) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java index 564ae6a33..f7f4e3d73 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java @@ -21,9 +21,7 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.item.ItemStack; import net.minecraft.item.PotionItem; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.particles.BlockParticleData; import net.minecraft.particles.IParticleData; -import net.minecraft.particles.ParticleTypes; import net.minecraft.potion.PotionUtils; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java index 7dfb7dc06..13ed0a475 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java @@ -10,6 +10,7 @@ import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTProcessors; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -115,7 +116,7 @@ public abstract class ZapperItem extends Item { }); applyCooldown(player, item, false); } - return new ActionResult(ActionResultType.SUCCESS, item); + return new ActionResult<>(ActionResultType.SUCCESS, item); } boolean mainHand = hand == Hand.MAIN_HAND; @@ -125,7 +126,7 @@ public abstract class ZapperItem extends Item { // Pass To Offhand if (mainHand && isSwap && gunInOtherHand) - return new ActionResult(ActionResultType.FAIL, item); + return new ActionResult<>(ActionResultType.FAIL, item); if (mainHand && !isSwap && gunInOtherHand) item.getTag() .putBoolean("_Swap", true); @@ -144,7 +145,7 @@ public abstract class ZapperItem extends Item { world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS, 1f, 0.5f); player.sendStatusMessage(msg.applyTextStyle(TextFormatting.RED), true); - return new ActionResult(ActionResultType.FAIL, item); + return new ActionResult<>(ActionResultType.FAIL, item); } BlockState stateToUse = Blocks.AIR.getDefaultState(); @@ -169,7 +170,7 @@ public abstract class ZapperItem extends Item { // No target if (pos == null || stateReplaced.getBlock() == Blocks.AIR) { applyCooldown(player, item, gunInOtherHand); - return new ActionResult(ActionResultType.SUCCESS, item); + return new ActionResult<>(ActionResultType.SUCCESS, item); } // Find exact position of gun barrel for VFX @@ -183,7 +184,7 @@ public abstract class ZapperItem extends Item { // Client side if (world.isRemote) { ZapperRenderHandler.dontAnimateItem(hand); - return new ActionResult(ActionResultType.SUCCESS, item); + return new ActionResult<>(ActionResultType.SUCCESS, item); } // Server side @@ -195,7 +196,7 @@ public abstract class ZapperItem extends Item { new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true)); } - return new ActionResult(ActionResultType.SUCCESS, item); + return new ActionResult<>(ActionResultType.SUCCESS, item); } public ITextComponent validateUsage(ItemStack item) { @@ -240,10 +241,13 @@ public abstract class ZapperItem extends Item { return UseAction.NONE; } - public static void setTileData(World world, BlockPos pos, CompoundNBT data) { - if (data != null) { + public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data) { + if (data != null && AllBlockTags.SAFE_NBT.matches(state)) { TileEntity tile = world.getTileEntity(pos); - if (tile != null && !tile.onlyOpsCanSetNbt()) { + if (tile != null) { + data = NBTProcessors.process(tile, data, true); + if (data == null) + return; data.putInt("x", pos.getX()); data.putInt("y", pos.getY()); data.putInt("z", pos.getZ()); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java index 5e27ad20c..954d06daf 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java @@ -135,7 +135,7 @@ public class BlockzapperItem extends ZapperItem { blocksnapshot.restore(true, false); return false; } - setTileData(world, placed, data); + setTileData(world, placed, state, data); if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java index 51401b113..abd142734 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java @@ -47,7 +47,7 @@ public enum TerrainTools { if (!isReplaceable(toReplace)) return; world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, data); + ZapperItem.setTileData(world, p, paintedState, data); }); break; case Flatten: @@ -67,13 +67,13 @@ public enum TerrainTools { if (!isReplaceable(toReplace)) return; world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, data); + ZapperItem.setTileData(world, p, paintedState, data); }); break; case Place: targetPositions.forEach(p -> { world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, data); + ZapperItem.setTileData(world, p, paintedState, data); }); break; case Replace: @@ -82,7 +82,7 @@ public enum TerrainTools { if (isReplaceable(toReplace)) return; world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, data); + ZapperItem.setTileData(world, p, paintedState, data); }); break; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java index de0eb97b4..3fb18767d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.block.redstone; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java index f6d1a61d3..0a4612eab 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java @@ -2,8 +2,11 @@ package com.simibubi.create.content.schematics; import com.mojang.datafixers.Dynamic; import com.mojang.datafixers.types.DynamicOps; +import com.simibubi.create.foundation.utility.NBTProcessors; + import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorldReader; @@ -24,8 +27,10 @@ public class SchematicProcessor extends StructureProcessor { public Template.BlockInfo process(IWorldReader world, BlockPos pos, Template.BlockInfo rawInfo, Template.BlockInfo info, PlacementSettings settings, @Nullable Template template) { if (info.nbt != null) { TileEntity te = info.state.createTileEntity(world); - if (te != null && te.onlyOpsCanSetNbt()) { - return new Template.BlockInfo(info.pos, info.state, null); + if (te != null) { + CompoundNBT nbt = NBTProcessors.process(te, info.nbt, false); + if (nbt != info.nbt) + return new Template.BlockInfo(info.pos, info.state, nbt); } } return info; diff --git a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java index 743cc5a3b..d9ea129c2 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java @@ -5,7 +5,6 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -14,8 +13,6 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Stream; -import org.apache.commons.io.IOUtils; - import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.Create; diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java index 8069187b7..aad69e69a 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java @@ -27,6 +27,7 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.NBTProcessors; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -466,8 +467,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC CompoundNBT data = null; if (AllBlockTags.SAFE_NBT.matches(blockState)) { TileEntity tile = blockReader.getTileEntity(target); - if (tile != null && !tile.onlyOpsCanSetNbt()) { + if (tile != null) { data = tile.write(new CompoundNBT()); + data = NBTProcessors.process(tile, data, true); } } launchBlock(target, icon, blockState, data); diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java index 1bef9185f..21fb1871d 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java @@ -154,7 +154,7 @@ public class SchematicItem extends Item { public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { if (!onItemUse(playerIn, handIn)) return super.onItemRightClick(worldIn, playerIn, handIn); - return new ActionResult(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn)); + return new ActionResult<>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn)); } private boolean onItemUse(PlayerEntity player, Hand hand) { diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java index 869f966f1..d15430671 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.schematics.packet; import java.util.function.Supplier; +import com.simibubi.create.content.schematics.SchematicProcessor; import com.simibubi.create.content.schematics.item.SchematicItem; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -36,6 +37,8 @@ public class SchematicPlacePacket extends SimplePacketBase { return; Template t = SchematicItem.loadSchematic(stack); PlacementSettings settings = SchematicItem.getSettings(stack); + if (player.canUseCommandBlock()) + settings.func_215220_b(SchematicProcessor.INSTANCE); // remove processor settings.setIgnoreEntities(false); t.addBlocksToWorld(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")), settings); diff --git a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java index e59a45521..2cbff0055 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; diff --git a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java new file mode 100644 index 000000000..8ca4d212f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java @@ -0,0 +1,57 @@ +package com.simibubi.create.foundation.utility; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.UnaryOperator; + +import javax.annotation.Nullable; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.text.ITextComponent; + +public final class NBTProcessors { + + private static final Map, UnaryOperator> processors = new HashMap<>(); + private static final Map, UnaryOperator> survivalProcessors = new HashMap<>(); + + public static synchronized void addProcessor(TileEntityType type, UnaryOperator processor) { + processors.put(type, processor); + } + + public static synchronized void addSurvivalProcessor(TileEntityType type, UnaryOperator processor) { + survivalProcessors.put(type, processor); + } + + static { + addProcessor(TileEntityType.SIGN, data -> { + for (int i = 0; i < 4; ++i) { + String s = data.getString("Text" + (i + 1)); + ITextComponent textcomponent = ITextComponent.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); + if (textcomponent != null && textcomponent.getStyle() != null + && textcomponent.getStyle().getClickEvent() != null) + return null; + } + return data; + }); + } + + private NBTProcessors() { + } + + @Nullable + public static CompoundNBT process(TileEntity tileEntity, CompoundNBT compound, boolean survival) { + if (compound == null) + return null; + TileEntityType type = tileEntity.getType(); + if (survival && survivalProcessors.containsKey(type)) + compound = survivalProcessors.get(type).apply(compound); + if (processors.containsKey(type)) + return processors.get(type).apply(compound); + if (tileEntity.onlyOpsCanSetNbt()) + return null; + return compound; + } + +} From 4a15fbcec36974b7bae71d5e937568bd004a5079 Mon Sep 17 00:00:00 2001 From: Snownee Date: Sun, 31 Jan 2021 15:28:14 +0800 Subject: [PATCH 09/11] Fix funnel filter dupe --- .../content/curiosities/zapper/ZapperItem.java | 4 ++-- .../zapper/blockzapper/BlockzapperItem.java | 2 +- .../zapper/terrainzapper/TerrainTools.java | 11 ++++++----- .../zapper/terrainzapper/WorldshaperItem.java | 2 +- .../create/foundation/utility/NBTProcessors.java | 12 ++++++++++++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java index 13ed0a475..44303bf94 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java @@ -241,11 +241,11 @@ public abstract class ZapperItem extends Item { return UseAction.NONE; } - public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data) { + public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data, PlayerEntity player) { if (data != null && AllBlockTags.SAFE_NBT.matches(state)) { TileEntity tile = world.getTileEntity(pos); if (tile != null) { - data = NBTProcessors.process(tile, data, true); + data = NBTProcessors.process(tile, data, !player.isCreative()); if (data == null) return; data.putInt("x", pos.getX()); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java index 954d06daf..21d555b6b 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java @@ -135,7 +135,7 @@ public class BlockzapperItem extends ZapperItem { blocksnapshot.restore(true, false); return false; } - setTileData(world, placed, state, data); + setTileData(world, placed, state, data, player); if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java index abd142734..3abb7fe27 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java @@ -10,6 +10,7 @@ import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -36,7 +37,7 @@ public enum TerrainTools { return this != Clear && this != Flatten; } - public void run(World world, List targetPositions, Direction facing, @Nullable BlockState paintedState, @Nullable CompoundNBT data) { + public void run(World world, List targetPositions, Direction facing, @Nullable BlockState paintedState, @Nullable CompoundNBT data, PlayerEntity player) { switch (this) { case Clear: targetPositions.forEach(p -> world.setBlockState(p, Blocks.AIR.getDefaultState())); @@ -47,7 +48,7 @@ public enum TerrainTools { if (!isReplaceable(toReplace)) return; world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data); + ZapperItem.setTileData(world, p, paintedState, data, player); }); break; case Flatten: @@ -67,13 +68,13 @@ public enum TerrainTools { if (!isReplaceable(toReplace)) return; world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data); + ZapperItem.setTileData(world, p, paintedState, data, player); }); break; case Place: targetPositions.forEach(p -> { world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data); + ZapperItem.setTileData(world, p, paintedState, data, player); }); break; case Replace: @@ -82,7 +83,7 @@ public enum TerrainTools { if (isReplaceable(toReplace)) return; world.setBlockState(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data); + ZapperItem.setTileData(world, p, paintedState, data, player); }); break; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java index 9f2e4d019..4e5df7686 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java @@ -77,7 +77,7 @@ public class WorldshaperItem extends ZapperItem { for (BlockPos blockPos : brush.getIncludedPositions()) affectedPositions.add(targetPos.add(blockPos)); PlacementPatterns.applyPattern(affectedPositions, stack); - tool.run(world, affectedPositions, raytrace.getFace(), stateToUse, data); + tool.run(world, affectedPositions, raytrace.getFace(), stateToUse, data, player); return true; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java index 8ca4d212f..1524913fb 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java @@ -6,6 +6,10 @@ import java.util.function.UnaryOperator; import javax.annotation.Nullable; +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.content.logistics.item.filter.FilterItem; + +import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; @@ -35,6 +39,14 @@ public final class NBTProcessors { } return data; }); + addSurvivalProcessor(AllTileEntities.FUNNEL.get(), data -> { + if (data.contains("Filter")) { + ItemStack filter = ItemStack.read(data.getCompound("Filter")); + if (filter.getItem() instanceof FilterItem) + data.remove("Filter"); + } + return data; + }); } private NBTProcessors() { From 5c64c2d94209d94c8f95f335ac43e75515af70e1 Mon Sep 17 00:00:00 2001 From: Snownee Date: Sun, 31 Jan 2021 16:06:45 +0800 Subject: [PATCH 10/11] Add server-side check for extendo-grip and contraption interaction --- .../sync/ContraptionInteractionPacket.java | 37 ++++++++++-------- .../tools/ExtendoGripInteractionPacket.java | 39 +++++++++++-------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java index 5960d43fc..83e37704b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java @@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.network.PacketBuffer; import net.minecraft.util.Direction; @@ -45,22 +46,26 @@ public class ContraptionInteractionPacket extends SimplePacketBase { @Override public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayerEntity sender = context.get() - .getSender(); - if (sender == null) - return; - Entity entityByID = sender.getServerWorld() - .getEntityByID(target); - if (!(entityByID instanceof AbstractContraptionEntity)) - return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand)) - sender.swingHand(interactionHand, true); - }); - context.get() - .setPacketHandled(true); + context.get().enqueueWork(() -> { + ServerPlayerEntity sender = context.get().getSender(); + if (sender == null) + return; + Entity entityByID = sender.getServerWorld().getEntityByID(target); + if (!(entityByID instanceof AbstractContraptionEntity)) + return; + AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; + double d = sender.getAttribute(PlayerEntity.REACH_DISTANCE).getValue(); + if (!sender.canEntityBeSeen(entityByID)) + d -= 3; + d *= d; + if (sender.getDistanceSq(entityByID) > d) { + // TODO log? + return; + } + if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand)) + sender.swingHand(interactionHand, true); + }); + context.get().setPacketHandled(true); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java index 63739b632..36364c95f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java @@ -5,6 +5,7 @@ import java.util.function.Supplier; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.network.PacketBuffer; import net.minecraft.util.Hand; @@ -53,25 +54,29 @@ public class ExtendoGripInteractionPacket extends SimplePacketBase { @Override public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayerEntity sender = context.get() - .getSender(); - if (sender == null) + context.get().enqueueWork(() -> { + ServerPlayerEntity sender = context.get().getSender(); + if (sender == null) + return; + Entity entityByID = sender.getServerWorld().getEntityByID(target); + if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) { + double d = sender.getAttribute(PlayerEntity.REACH_DISTANCE).getValue(); + if (!sender.canEntityBeSeen(entityByID)) + d -= 3; + d *= d; + if (sender.getDistanceSq(entityByID) > d) { + // TODO log? return; - Entity entityByID = sender.getServerWorld() - .getEntityByID(target); - if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) { - if (interactionHand == null) - sender.attackTargetEntityWithCurrentItem(entityByID); - else if (specificPoint == null) - sender.interactOn(entityByID, interactionHand); - else - entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand); } - }); - context.get() - .setPacketHandled(true); + if (interactionHand == null) + sender.attackTargetEntityWithCurrentItem(entityByID); + else if (specificPoint == null) + sender.interactOn(entityByID, interactionHand); + else + entityByID.applyPlayerInteraction(sender, specificPoint, interactionHand); + } + }); + context.get().setPacketHandled(true); } } From 25daf28205c7bdc8f6e52fbe3f686bfba3dae12a Mon Sep 17 00:00:00 2001 From: Snownee Date: Sat, 6 Feb 2021 04:21:07 +0800 Subject: [PATCH 11/11] Format codes --- .../schematics/SchematicProcessor.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java index 0a4612eab..985338d5d 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java @@ -23,8 +23,9 @@ public class SchematicProcessor extends StructureProcessor { public static final SchematicProcessor INSTANCE = new SchematicProcessor(); @Nullable - @Override - public Template.BlockInfo process(IWorldReader world, BlockPos pos, Template.BlockInfo rawInfo, Template.BlockInfo info, PlacementSettings settings, @Nullable Template template) { + @Override + public Template.BlockInfo process(IWorldReader world, BlockPos pos, Template.BlockInfo rawInfo, + Template.BlockInfo info, PlacementSettings settings, @Nullable Template template) { if (info.nbt != null) { TileEntity te = info.state.createTileEntity(world); if (te != null) { @@ -33,26 +34,25 @@ public class SchematicProcessor extends StructureProcessor { return new Template.BlockInfo(info.pos, info.state, nbt); } } - return info; - } + return info; + } @Nullable - @Override - public Template.EntityInfo processEntity(IWorldReader world, BlockPos pos, Template.EntityInfo rawInfo, Template.EntityInfo info, PlacementSettings settings, Template template) { - return EntityType.readEntityType(info.nbt) - .flatMap(type -> { - if (world instanceof World) { - Entity e = type.create((World) world); - if (e != null && !e.ignoreItemEntityData()) { - return Optional.of(info); - } + @Override + public Template.EntityInfo processEntity(IWorldReader world, BlockPos pos, Template.EntityInfo rawInfo, + Template.EntityInfo info, PlacementSettings settings, Template template) { + return EntityType.readEntityType(info.nbt).flatMap(type -> { + if (world instanceof World) { + Entity e = type.create((World) world); + if (e != null && !e.ignoreItemEntityData()) { + return Optional.of(info); } - return Optional.empty(); - }) - .orElse(null); - } + } + return Optional.empty(); + }).orElse(null); + } - @Override + @Override protected IStructureProcessorType getType() { return dynamic -> INSTANCE; }