diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 294fd7aef..fb6f24a64 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -409,19 +409,19 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json a6d814f94926d88764c38862cc4ece9c367e023b assets/create/lang/en_ud.json d1838140c8383ee4537db90eb8f657d0c268fe91 assets/create/lang/en_us.json -9d6f26ca7b59d3707ce996e513358cc9b873cad1 assets/create/lang/unfinished/de_de.json -7fafb7565349aa52f4ccb829d4886a179eb547dc assets/create/lang/unfinished/es_es.json -822b912d290d40c5f02011393af44bf37684f9b4 assets/create/lang/unfinished/es_mx.json -502d761465a0de7aeb15acec4147b8ec8bee92cf assets/create/lang/unfinished/fr_fr.json -dac15c17578fb37bbdb874cee5a0a078110b7481 assets/create/lang/unfinished/it_it.json -fd270c9c8bc46d4df21aa04ecc7bf059011e4b3e assets/create/lang/unfinished/ja_jp.json -a5b002e047a2f509a8d35b9e638627f970b4810e assets/create/lang/unfinished/ko_kr.json -50f65aaba8c4fec5404ab1fc40f74b4970a55edd assets/create/lang/unfinished/nl_nl.json -ff61e567f15ded6ba127522af03860232069cdd2 assets/create/lang/unfinished/pl_pl.json -a7a28fb3896bc38e00f746e650433160f5b53c90 assets/create/lang/unfinished/pt_br.json -ffa1901b392719634403048419d29b268704bd10 assets/create/lang/unfinished/ru_ru.json -38b843c5232167876b3678328b47ec95f30cf69f assets/create/lang/unfinished/zh_cn.json -b806d1e6fe9ebee27f417a3c4d6c818124ee4cde assets/create/lang/unfinished/zh_tw.json +4fcda300efe5a2ad8695b5ae3f24a54ea109a954 assets/create/lang/unfinished/de_de.json +6a1dde57b2224d4b0287ebc705d6a75d329b5e1f assets/create/lang/unfinished/es_es.json +93ee0e30a56b405a9e766d353c36276e36a84b5c assets/create/lang/unfinished/es_mx.json +49a691320c73e09f921cd0ea97398126231e99fa assets/create/lang/unfinished/fr_fr.json +cf14b3828b6c11013f606f277d88fb63245bb2a8 assets/create/lang/unfinished/it_it.json +73c1c1489833cbcb28bb1ce90541c8c8bdf329c0 assets/create/lang/unfinished/ja_jp.json +924303b9bcf56aedbbfc46108655f71324308e12 assets/create/lang/unfinished/ko_kr.json +079aea6843e756efbfca0976983be1957863717c assets/create/lang/unfinished/nl_nl.json +b7bab15167400ee48a9728f81446e572c494fd8d assets/create/lang/unfinished/pl_pl.json +07e84cc3eee3faa1ab3d26e0c85c7f09c8573368 assets/create/lang/unfinished/pt_br.json +6ffb0cf20d712aee23a42a9ec440dd7dc92293d6 assets/create/lang/unfinished/ru_ru.json +0ae98a18e59f478da41d8c5d832737b65f6a8c8a assets/create/lang/unfinished/zh_cn.json +4c96e5a76e72368a59190b7588d389fdd2cc75e1 assets/create/lang/unfinished/zh_tw.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json @@ -2726,7 +2726,7 @@ cecaac07bd275bb1ae9e302f0bf44b581e74105d data/create/loot_tables/blocks/rope_pul aa6af37356d65105efab2503ffe75f778cfe873b data/create/loot_tables/blocks/rotation_speed_controller.json 30de11bec82606fead9d6bff7bba0232e97f1039 data/create/loot_tables/blocks/sail_frame.json 069701cb804b6522c18624a0d4f3f949ff8b0281 data/create/loot_tables/blocks/schematic_table.json -c4a89145334addfd0dd1fedf7fa75ba07a7d3490 data/create/loot_tables/blocks/schematicannon.json +a2b172dc749176d4df34729007019605fc6dd150 data/create/loot_tables/blocks/schematicannon.json af1bbbb8236b4ab05a6a8edc6db960bc758cbdf3 data/create/loot_tables/blocks/scoria.json bb670ac5dd2fa4c743bc268cd0547926eb6cdb68 data/create/loot_tables/blocks/scoria_bricks.json a7217ea301a282d0ef52f2d8c06dd8683398408d data/create/loot_tables/blocks/scoria_bricks_slab.json diff --git a/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json b/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json index 255327042..16d2e3ed1 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json +++ b/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json @@ -6,6 +6,19 @@ "entries": [ { "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Options", + "target": "BlockEntityTag.Options", + "op": "replace" + } + ] + } + ], "name": "create:schematicannon" } ], diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 472b8e8a2..5ea72cd61 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -215,6 +215,16 @@ public class AllBlocks { REGISTRATE.block("schematicannon", SchematicannonBlock::new) .initialProperties(() -> Blocks.DISPENSER) .blockstate((ctx, prov) -> prov.simpleBlock(ctx.getEntry(), AssetLookup.partialBaseModel(ctx, prov))) + .loot((lt, block) -> { + Builder builder = LootTable.builder(); + IBuilder survivesExplosion = SurvivesExplosion.builder(); + lt.registerLootTable(block, builder.addLootPool(LootPool.builder() + .acceptCondition(survivesExplosion) + .rolls(ConstantRange.of(1)) + .addEntry(ItemLootEntry.builder(AllBlocks.SCHEMATICANNON.get().asItem()) + .acceptFunction(CopyNbt.func_215881_a(CopyNbt.Source.BLOCK_ENTITY) + .func_216056_a("Options", "BlockEntityTag.Options"))))); + }) .item() .transform(customItemModel()) .register(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java index 09c2653a2..1da586170 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java @@ -54,6 +54,7 @@ import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Hand; +import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; @@ -492,29 +493,55 @@ public class CartAssemblerBlock extends AbstractRailBlock public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { World world = context.getWorld(); if (world.isRemote) return ActionResultType.SUCCESS; BlockPos pos = context.getPos(); - BlockState newState = state.with(RAIL_SHAPE, - state.get(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH); - if (state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL - || state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS) { - newState = newState.with(RAIL_TYPE, AllBlocks.CONTROLLER_RAIL.get() - .rotate(AllBlocks.CONTROLLER_RAIL.getDefaultState() - .with(ControllerRailBlock.SHAPE, state.get(RAIL_SHAPE)) - .with(ControllerRailBlock.BACKWARDS, - state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS), - Rotation.CLOCKWISE_90) - .get(ControllerRailBlock.BACKWARDS) ? CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS - : CartAssembleRailType.CONTROLLER_RAIL); - } - context.getWorld() - .setBlockState(pos, newState, 3); + world.setBlockState(pos, rotate(state, Rotation.CLOCKWISE_90), 3); world.notifyNeighborsOfStateChange(pos.down(), this); return ActionResultType.SUCCESS; } + + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + if (rotation == Rotation.NONE) + return state; + + boolean is_controller_rail_backwards = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS; + boolean is_controller_rail = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL || is_controller_rail_backwards; + BlockState base = AllBlocks.CONTROLLER_RAIL.getDefaultState() + .with(ControllerRailBlock.SHAPE, state.get(RAIL_SHAPE)) + .with(ControllerRailBlock.BACKWARDS, is_controller_rail_backwards) + .rotate(rotation); + if (is_controller_rail) { + state = state.with(RAIL_TYPE, + base.get(ControllerRailBlock.BACKWARDS) ? CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS : + CartAssembleRailType.CONTROLLER_RAIL + ); + } + return state.with(RAIL_SHAPE, base.get(ControllerRailBlock.SHAPE)); + } + + @Override + public BlockState mirror(BlockState state, Mirror mirror) { + if (mirror == Mirror.NONE) + return state; + + boolean is_controller_rail_backwards = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS; + boolean is_controller_rail = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL || is_controller_rail_backwards; + BlockState base = AllBlocks.CONTROLLER_RAIL.getDefaultState() + .with(ControllerRailBlock.SHAPE, state.get(RAIL_SHAPE)) + .with(ControllerRailBlock.BACKWARDS, is_controller_rail_backwards) + .mirror(mirror); + if (is_controller_rail) { + state = state.with(RAIL_TYPE, + base.get(ControllerRailBlock.BACKWARDS) ? CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS : + CartAssembleRailType.CONTROLLER_RAIL + ); + } + return state.with(RAIL_SHAPE, base.get(ControllerRailBlock.SHAPE)); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java index 9592b9d02..19a563c35 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java @@ -169,6 +169,20 @@ public class GantryShaftBlock extends DirectionalKineticBlock { return onWrenched; } + @Override + public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onBlockAdded(state, worldIn, pos, oldState, isMoving); + + if (!worldIn.isRemote() && oldState.getBlock().is(AllBlocks.GANTRY_SHAFT.get())) { + Part oldPart = oldState.get(PART), part = state.get(PART); + if ((oldPart != Part.MIDDLE && part == Part.MIDDLE) || (oldPart == Part.SINGLE && part != Part.SINGLE)) { + TileEntity te = worldIn.getTileEntity(pos); + if (te instanceof GantryShaftTileEntity) + ((GantryShaftTileEntity) te).checkAttachedCarriageBlocks(); + } + } + } + @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, boolean p_220069_6_) { @@ -260,7 +274,7 @@ public class GantryShaftBlock extends DirectionalKineticBlock { return super.areStatesKineticallyEquivalent(oldState, newState) && oldState.get(POWERED) == newState.get(POWERED); } - + @Override public float getParticleTargetRadius() { return .35f; @@ -270,7 +284,7 @@ public class GantryShaftBlock extends DirectionalKineticBlock { public float getParticleInitialRadius() { return .25f; } - + @Override public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java index 681a01269..2f9fe658a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java @@ -19,15 +19,12 @@ public class GantryShaftTileEntity extends KineticTileEntity { super(typeIn); } - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - + public void checkAttachedCarriageBlocks() { if (!canAssembleOn()) return; for (Direction d : Iterate.directions) { if (d.getAxis() == getBlockState().get(GantryShaftBlock.FACING) - .getAxis()) + .getAxis()) continue; BlockPos offset = pos.offset(d); BlockState pinionState = world.getBlockState(offset); @@ -39,7 +36,12 @@ public class GantryShaftTileEntity extends KineticTileEntity { if (tileEntity instanceof GantryCarriageTileEntity) ((GantryCarriageTileEntity) tileEntity).queueAssembly(); } + } + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + checkAttachedCarriageBlocks(); } @Override @@ -99,7 +101,7 @@ public class GantryShaftTileEntity extends KineticTileEntity { return 0; return MathHelper.clamp(-getSpeed() / 512f, -.49f, .49f); } - + @Override protected boolean isNoisy() { return false; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java index ae0a584e3..0229882b3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java @@ -122,14 +122,14 @@ public class ArmTileEntity extends KineticTileEntity { } if (world.isRemote) return; - + if (phase == Phase.MOVE_TO_INPUT) collectItem(); else if (phase == Phase.MOVE_TO_OUTPUT) depositItem(); else if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) searchForItem(); - + if (targetReached) lazyTick(); } @@ -142,7 +142,7 @@ public class ArmTileEntity extends KineticTileEntity { return; if (chasedPointProgress < .5f) return; - if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) + if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) checkForMusic(); if (phase == Phase.SEARCH_OUTPUTS) searchForDestination(); @@ -175,7 +175,7 @@ public class ArmTileEntity extends KineticTileEntity { } private boolean tickMovementProgress() { - boolean targetReachedPreviously = chasedPointProgress >= 1; + boolean targetReachedPreviously = chasedPointProgress >= 1; chasedPointProgress += Math.min(256, Math.abs(getSpeed())) / 1024f; if (chasedPointProgress > 1) chasedPointProgress = 1; @@ -349,7 +349,7 @@ public class ArmTileEntity extends KineticTileEntity { chasedPointIndex = -1; sendData(); markDirty(); - + if (!prevHeld.isItemEqual(heldItem)) world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, .5f + Create.random.nextFloat() * .25f); @@ -416,23 +416,26 @@ public class ArmTileEntity extends KineticTileEntity { markDirty(); } + public void writeInteractionPoints(CompoundNBT compound) { + if (updateInteractionPoints) { + compound.put("InteractionPoints", interactionPointTag); + } else { + ListNBT pointsNBT = new ListNBT(); + inputs.stream() + .map(aip -> aip.serialize(pos)) + .forEach(pointsNBT::add); + outputs.stream() + .map(aip -> aip.serialize(pos)) + .forEach(pointsNBT::add); + compound.put("InteractionPoints", pointsNBT); + } + } + @Override public void write(CompoundNBT compound, boolean clientPacket) { super.write(compound, clientPacket); - if (updateInteractionPoints) { - compound.put("InteractionPoints", interactionPointTag); - - } else { - ListNBT pointsNBT = new ListNBT(); - inputs.stream() - .map(aip -> aip.serialize(pos)) - .forEach(pointsNBT::add); - outputs.stream() - .map(aip -> aip.serialize(pos)) - .forEach(pointsNBT::add); - compound.put("InteractionPoints", pointsNBT); - } + writeInteractionPoints(compound); NBTHelper.writeEnum(compound, "Phase", phase); compound.putBoolean("Powered", redstoneLocked); @@ -441,6 +444,13 @@ public class ArmTileEntity extends KineticTileEntity { compound.putFloat("MovementProgress", chasedPointProgress); } + @Override + public void writeSafe(CompoundNBT compound, boolean clientPacket) { + super.writeSafe(compound, clientPacket); + + writeInteractionPoints(compound); + } + @Override protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { int previousIndex = chasedPointIndex; 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 8a06c2464..ef443d62d 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 @@ -28,10 +28,15 @@ import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.IPartialSafeNBT; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTProcessors; +import net.minecraft.block.AbstractRailBlock; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.PistonHeadBlock; @@ -79,6 +84,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC STOPPED, PAUSED, RUNNING; } + public enum PrintStage { + BLOCKS, DEFERRED_BLOCKS, ENTITIES + } + // Inventory public SchematicannonInventory inventory; @@ -99,12 +108,14 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC private int skipsLeft; private boolean blockSkipped; private int printingEntityIndex; + private PrintStage printStage; public BlockPos target; public BlockPos previousTarget; public LinkedHashSet> attachedInventories; public List flyingBlocks; public MaterialChecklist checklist; + public List deferredBlocks; // Gui information public float fuelLevel; @@ -142,7 +153,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC inventory = new SchematicannonInventory(this); statusMsg = "idle"; state = State.STOPPED; - printingEntityIndex = -1; + printingEntityIndex = 0; + printStage = PrintStage.BLOCKS; + deferredBlocks = new LinkedList<>(); replaceMode = 2; checklist = new MaterialChecklist(); } @@ -198,8 +211,14 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC replaceTileEntities = options.getBoolean("ReplaceTileEntities"); // Printer & Flying Blocks + if (compound.contains("PrintStage")) + printStage = PrintStage.valueOf(compound.getString("PrintStage")); if (compound.contains("Target")) target = NBTUtil.readBlockPos(compound.getCompound("Target")); + if (compound.contains("DeferredBlocks")) + compound.getList("DeferredBlocks", 10).stream() + .map(p -> NBTUtil.readBlockPos((CompoundNBT) p)) + .collect(Collectors.toCollection(() -> deferredBlocks)); if (compound.contains("FlyingBlocks")) readFlyingBlocks(compound); @@ -273,12 +292,20 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC compound.put("Options", options); // Printer & Flying Blocks + compound.putString("PrintStage", printStage.name()); + if (target != null) compound.put("Target", NBTUtil.writeBlockPos(target)); - ListNBT tagBlocks = new ListNBT(); + + ListNBT tagDeferredBlocks = new ListNBT(); + for (BlockPos p : deferredBlocks) + tagDeferredBlocks.add(NBTUtil.writeBlockPos(p)); + compound.put("DeferredBlocks", tagDeferredBlocks); + + ListNBT tagFlyingBlocks = new ListNBT(); for (LaunchedItem b : flyingBlocks) - tagBlocks.add(b.serializeNBT()); - compound.put("FlyingBlocks", tagBlocks); + tagFlyingBlocks.add(b.serializeNBT()); + compound.put("FlyingBlocks", tagFlyingBlocks); super.write(compound, clientPacket); } @@ -388,7 +415,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC target = schematicAnchor.add(currentPos); } - boolean entityMode = printingEntityIndex >= 0; + boolean entityMode = printStage == PrintStage.ENTITIES; // Check block if (!getWorld().isAreaLoaded(target, 0)) { @@ -471,13 +498,18 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC launchBlock(target, icon, blockState, null); } else { CompoundNBT data = null; - if (AllBlockTags.SAFE_NBT.matches(blockState)) { - TileEntity tile = blockReader.getTileEntity(target); - if (tile != null) { + TileEntity tile = blockReader.getTileEntity(target); + if (tile != null) { + if (AllBlockTags.SAFE_NBT.matches(blockState)) { data = tile.write(new CompoundNBT()); data = NBTProcessors.process(tile, data, true); + } else if (tile instanceof IPartialSafeNBT) { + data = new CompoundNBT(); + ((IPartialSafeNBT) tile).writeSafe(data, false); + data = NBTProcessors.process(tile, data, true); } } + launchBlock(target, icon, blockState, data); } @@ -563,7 +595,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC schematicLoaded = true; state = State.PAUSED; statusMsg = "ready"; - printingEntityIndex = -1; + printingEntityIndex = 0; + printStage = PrintStage.BLOCKS; + deferredBlocks.clear(); updateChecklist(); sendUpdate = true; blocksToPlace += blocksPlaced; @@ -649,22 +683,33 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC protected void advanceCurrentPos() { List entities = blockReader.getEntities() .collect(Collectors.toList()); - if (printingEntityIndex != -1) { - printingEntityIndex++; - // End of entities reached - if (printingEntityIndex >= entities.size()) { - finishedPrinting(); - return; + if (printStage == PrintStage.BLOCKS) { + MutableBoundingBox bounds = blockReader.getBounds(); + while (tryAdvanceCurrentPos(bounds, entities)) { + deferredBlocks.add(currentPos); } - - currentPos = entities.get(printingEntityIndex) - .getBlockPos() - .subtract(schematicAnchor); - return; } - MutableBoundingBox bounds = blockReader.getBounds(); + if (printStage == PrintStage.DEFERRED_BLOCKS) { + if (deferredBlocks.isEmpty()) { + printStage = PrintStage.ENTITIES; + } else { + currentPos = deferredBlocks.remove(0); + } + } + + if (printStage == PrintStage.ENTITIES) { + if (printingEntityIndex < entities.size()) { + currentPos = entities.get(printingEntityIndex).getBlockPos().subtract(schematicAnchor); + printingEntityIndex++; + } else { + finishedPrinting(); + } + } + } + + protected boolean tryAdvanceCurrentPos(MutableBoundingBox bounds, List entities) { currentPos = currentPos.offset(Direction.EAST); BlockPos posInBounds = currentPos.add(-bounds.minX, -bounds.minY, -bounds.minZ); @@ -675,15 +720,16 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC // End of blocks reached if (currentPos.getY() > bounds.getYSize()) { - printingEntityIndex = 0; - if (entities.isEmpty()) { - finishedPrinting(); - return; - } - currentPos = entities.get(0) - .getBlockPos() - .subtract(schematicAnchor); + printStage = PrintStage.DEFERRED_BLOCKS; + return false; } + + return shouldDeferBlock(blockReader.getBlockState(schematicAnchor.add(currentPos))); + } + + public static boolean shouldDeferBlock(BlockState state) { + Block block = state.getBlock(); + return block instanceof AbstractRailBlock || block.is(AllBlocks.GANTRY_CARRIAGE.get()); } public void finishedPrinting() { @@ -705,10 +751,12 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC blockReader = null; missingItem = null; sendUpdate = true; - printingEntityIndex = -1; + printingEntityIndex = 0; + printStage = PrintStage.BLOCKS; schematicProgress = 0; blocksPlaced = 0; blocksToPlace = 0; + deferredBlocks.clear(); } protected boolean shouldPlace(BlockPos pos, BlockState state) { diff --git a/src/main/java/com/simibubi/create/foundation/mixin/ModelDataRefreshMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/ModelDataRefreshMixin.java new file mode 100644 index 000000000..151a0a7c6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/ModelDataRefreshMixin.java @@ -0,0 +1,37 @@ +package com.simibubi.create.foundation.mixin; + +import com.simibubi.create.content.schematics.SchematicWorld; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.client.model.ModelDataManager; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.Minecraft; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(ModelDataManager.class) +public class ModelDataRefreshMixin { + + /** + * Normally ModelDataManager will throw an exception if a tile entity tries + * to refresh its model data from a world the client isn't currently in, + * but we need that to not happen for tile entities in fake schematic + * worlds, so in those cases just do nothing instead. + */ + @Inject(at = @At("HEAD"), method = "requestModelDataRefresh", cancellable = true, remap = false) + private static void requestModelDataRefresh(TileEntity te, CallbackInfo ci) { + if (te != null) { + World world = te.getWorld(); + if (world != Minecraft.getInstance().world && world instanceof SchematicWorld) + ci.cancel(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java index a589bc7ca..e036d7dab 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java @@ -8,6 +8,8 @@ import java.util.function.Consumer; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.utility.IPartialSafeNBT; + import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.ITickableTileEntity; @@ -16,7 +18,7 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.items.CapabilityItemHandler; -public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity { +public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity, IPartialSafeNBT { private final Map, TileEntityBehaviour> behaviours; // Internally maintained to be identical to behaviorMap.values() in order to improve iteration performance. @@ -118,6 +120,14 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka behaviourList.forEach(tb -> tb.write(compound, clientPacket)); } + public void writeSafe(CompoundNBT compound, boolean clientPacket) { + super.write(compound); + behaviourList.forEach(tb -> { + if (tb.isSafeNBT()) + tb.write(compound, clientPacket); + }); + } + @Override public void remove() { forEachBehaviour(TileEntityBehaviour::remove); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java index 925677123..931b5f4bd 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java @@ -42,6 +42,8 @@ public abstract class TileEntityBehaviour { } + public boolean isSafeNBT() { return false; } + public void onBlockChanged(BlockState oldState) { } @@ -94,5 +96,4 @@ public abstract class TileEntityBehaviour { SmartTileEntity ste = (SmartTileEntity) te; return ste.getBehaviour(type); } - } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java index 803476b13..c6b7acebe 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java @@ -57,6 +57,9 @@ public class FilteringBehaviour extends TileEntityBehaviour { fluidFilter = false; } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { nbt.put("Filter", getFilter().serializeNBT()); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java index 88097a681..9a7f0a490 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java @@ -58,6 +58,9 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { removeFilter(d); } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { nbt.put("Filters", NBTHelper.writeCompoundList(sidedFilters.entrySet(), entry -> { diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java index 3d708e8f1..27d529ca7 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java @@ -115,6 +115,9 @@ public class LinkBehaviour extends TileEntityBehaviour { getHandler().removeFromNetwork(this); } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { super.write(nbt, clientPacket); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java index c67fc80e0..d189a689d 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java @@ -54,6 +54,9 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { ticksUntilScrollPacket = -1; } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { nbt.putInt("ScrollValue", value); @@ -95,7 +98,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { clientCallback = valueCallback; return this; } - + public ScrollValueBehaviour withCallback(Consumer valueCallback) { callback = valueCallback; return this; @@ -126,7 +129,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { this.unit = unit; return this; } - + public ScrollValueBehaviour onlyActiveWhen(Supplier condition) { isActive = condition; return this; @@ -168,7 +171,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { public BehaviourType getType() { return TYPE; } - + public boolean isActive() { return isActive.get(); } @@ -182,7 +185,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { public void setLabel(ITextComponent label) { this.label = label; } - + public static class StepContext { public int currentValue; public boolean forward; diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java index 59db72bcf..3f1bb7fd9 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java @@ -20,6 +20,9 @@ public class DeferralBehaviour extends TileEntityBehaviour { this.callback = callback; } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { nbt.putBoolean("NeedsUpdate", needsUpdate); @@ -38,7 +41,7 @@ public class DeferralBehaviour extends TileEntityBehaviour { if (needsUpdate && callback.get()) needsUpdate = false; } - + public void scheduleUpdate() { needsUpdate = true; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java index a70af7ca1..cc76d5dbe 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java @@ -1,9 +1,18 @@ package com.simibubi.create.foundation.utility; +import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; import javax.annotation.Nullable; +import net.minecraft.block.AbstractRailBlock; +import net.minecraft.block.RailBlock; + +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraftforge.common.util.BlockSnapshot; + import org.apache.commons.lang3.mutable.MutableInt; import com.simibubi.create.AllBlocks; @@ -234,6 +243,24 @@ public class BlockHelper { .isEmpty(); } + private static void placeRailWithoutUpdate(World world, BlockState state, BlockPos target) { + int i = target.getX() & 15; + int j = target.getY(); + int k = target.getZ() & 15; + Chunk chunk = world.getChunkAt(target); + ChunkSection chunksection = chunk.getSections()[j >> 4]; + if (chunksection == Chunk.EMPTY_SECTION) { + chunksection = new ChunkSection(j >> 4 << 4); + chunk.getSections()[j >> 4] = chunksection; + } + BlockState old = chunksection.setBlockState(i, j & 15, k, state); + chunk.markDirty(); + world.markAndNotifyBlock(target, chunk, old, state, 82, 512); + + world.setBlockState(target, state, 82); + world.neighborChanged(target, world.getBlockState(target.down()).getBlock(), target.down()); + } + public static void placeSchematicBlock(World world, BlockState state, BlockPos target, ItemStack stack, @Nullable CompoundNBT data) { // Piston @@ -268,7 +295,13 @@ public class BlockHelper { Block.spawnDrops(state, world, target); return; } - world.setBlockState(target, state, 18); + + if (state.getBlock() instanceof AbstractRailBlock) { + placeRailWithoutUpdate(world, state, target); + } else { + world.setBlockState(target, state, 18); + } + if (data != null) { TileEntity tile = world.getTileEntity(target); if (tile != null) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/IPartialSafeNBT.java b/src/main/java/com/simibubi/create/foundation/utility/IPartialSafeNBT.java new file mode 100644 index 000000000..ae1ca8a9d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/IPartialSafeNBT.java @@ -0,0 +1,7 @@ +package com.simibubi.create.foundation.utility; + +import net.minecraft.nbt.CompoundNBT; + +public interface IPartialSafeNBT { + public void writeSafe(CompoundNBT compound, boolean clientPacket); +} diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 3bc4de366..db6a800f6 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -19,7 +19,8 @@ "StoreProjectionMatrixMixin", "TileRemoveMixin", "TileWorldHookMixin", - "WindowResizeMixin" + "WindowResizeMixin", + "ModelDataRefreshMixin" ], "injectors": { "defaultRequire": 1