Add NBTProcessors to enable detailed control to tile data.

Add safe check when contraption blocks adding back to world
This commit is contained in:
Snownee 2021-01-31 14:56:46 +08:00
parent 0c5e67e347
commit c5447d5b9c
17 changed files with 98 additions and 29 deletions

View file

@ -23,6 +23,7 @@
"create:redstone_link", "create:redstone_link",
"create:analog_lever", "create:analog_lever",
"create:adjustable_repeater", "create:adjustable_repeater",
"create:adjustable_pulse_repeater" "create:adjustable_pulse_repeater",
"#minecraft:signs"
] ]
} }

View file

@ -187,5 +187,7 @@ public class AllTags {
AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS); AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS);
AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE); AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.CAMPFIRE, Blocks.LAVA, Blocks.FIRE);
AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS);
} }
} }

View file

@ -8,7 +8,6 @@ import java.util.stream.Collectors;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter; 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 com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;

View file

@ -1,6 +1,5 @@
package com.simibubi.create.content.contraptions.components.fan; package com.simibubi.create.content.contraptions.components.fan;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;

View file

@ -48,6 +48,7 @@ import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper; 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.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
@ -797,6 +798,8 @@ public abstract class Contraption {
TileEntity tileEntity = world.getTileEntity(targetPos); TileEntity tileEntity = world.getTileEntity(targetPos);
CompoundNBT tag = block.nbt; CompoundNBT tag = block.nbt;
if (tileEntity != null)
tag = NBTProcessors.process(tileEntity, tag, false);
if (tileEntity != null && tag != null) { if (tileEntity != null && tag != null) {
tag.putInt("x", targetPos.getX()); tag.putInt("x", targetPos.getX());
tag.putInt("y", targetPos.getY()); tag.putInt("y", targetPos.getY());
@ -828,7 +831,8 @@ public abstract class Contraption {
} }
for (BlockInfo block : blocks.values()) { for (BlockInfo block : blocks.values()) {
BlockPos targetPos = transform.apply(block.pos); 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++) for (int i = 0; i < inventory.getSlots(); i++)

View file

@ -21,9 +21,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.PotionItem; import net.minecraft.item.PotionItem;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.BlockParticleData;
import net.minecraft.particles.IParticleData; import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.potion.PotionUtils; import net.minecraft.potion.PotionUtils;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;

View file

@ -10,6 +10,7 @@ import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -115,7 +116,7 @@ public abstract class ZapperItem extends Item {
}); });
applyCooldown(player, item, false); applyCooldown(player, item, false);
} }
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
boolean mainHand = hand == Hand.MAIN_HAND; boolean mainHand = hand == Hand.MAIN_HAND;
@ -125,7 +126,7 @@ public abstract class ZapperItem extends Item {
// Pass To Offhand // Pass To Offhand
if (mainHand && isSwap && gunInOtherHand) if (mainHand && isSwap && gunInOtherHand)
return new ActionResult<ItemStack>(ActionResultType.FAIL, item); return new ActionResult<>(ActionResultType.FAIL, item);
if (mainHand && !isSwap && gunInOtherHand) if (mainHand && !isSwap && gunInOtherHand)
item.getTag() item.getTag()
.putBoolean("_Swap", true); .putBoolean("_Swap", true);
@ -144,7 +145,7 @@ public abstract class ZapperItem extends Item {
world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS, world.playSound(player, player.getPosition(), AllSoundEvents.BLOCKZAPPER_DENY.get(), SoundCategory.BLOCKS,
1f, 0.5f); 1f, 0.5f);
player.sendStatusMessage(msg.applyTextStyle(TextFormatting.RED), true); player.sendStatusMessage(msg.applyTextStyle(TextFormatting.RED), true);
return new ActionResult<ItemStack>(ActionResultType.FAIL, item); return new ActionResult<>(ActionResultType.FAIL, item);
} }
BlockState stateToUse = Blocks.AIR.getDefaultState(); BlockState stateToUse = Blocks.AIR.getDefaultState();
@ -169,7 +170,7 @@ public abstract class ZapperItem extends Item {
// No target // No target
if (pos == null || stateReplaced.getBlock() == Blocks.AIR) { if (pos == null || stateReplaced.getBlock() == Blocks.AIR) {
applyCooldown(player, item, gunInOtherHand); applyCooldown(player, item, gunInOtherHand);
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
// Find exact position of gun barrel for VFX // Find exact position of gun barrel for VFX
@ -183,7 +184,7 @@ public abstract class ZapperItem extends Item {
// Client side // Client side
if (world.isRemote) { if (world.isRemote) {
ZapperRenderHandler.dontAnimateItem(hand); ZapperRenderHandler.dontAnimateItem(hand);
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
// Server side // Server side
@ -195,7 +196,7 @@ public abstract class ZapperItem extends Item {
new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true)); new ZapperBeamPacket(barrelPos, raytrace.getHitVec(), hand, true));
} }
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, item); return new ActionResult<>(ActionResultType.SUCCESS, item);
} }
public ITextComponent validateUsage(ItemStack item) { public ITextComponent validateUsage(ItemStack item) {
@ -240,10 +241,13 @@ public abstract class ZapperItem extends Item {
return UseAction.NONE; return UseAction.NONE;
} }
public static void setTileData(World world, BlockPos pos, CompoundNBT data) { public static void setTileData(World world, BlockPos pos, BlockState state, CompoundNBT data) {
if (data != null) { if (data != null && AllBlockTags.SAFE_NBT.matches(state)) {
TileEntity tile = world.getTileEntity(pos); 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("x", pos.getX());
data.putInt("y", pos.getY()); data.putInt("y", pos.getY());
data.putInt("z", pos.getZ()); data.putInt("z", pos.getZ());

View file

@ -135,7 +135,7 @@ public class BlockzapperItem extends ZapperItem {
blocksnapshot.restore(true, false); blocksnapshot.restore(true, false);
return false; return false;
} }
setTileData(world, placed, data); setTileData(world, placed, state, data);
if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) { if (player instanceof ServerPlayerEntity && world instanceof ServerWorld) {
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player; ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;

View file

@ -47,7 +47,7 @@ public enum TerrainTools {
if (!isReplaceable(toReplace)) if (!isReplaceable(toReplace))
return; return;
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data);
}); });
break; break;
case Flatten: case Flatten:
@ -67,13 +67,13 @@ public enum TerrainTools {
if (!isReplaceable(toReplace)) if (!isReplaceable(toReplace))
return; return;
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data);
}); });
break; break;
case Place: case Place:
targetPositions.forEach(p -> { targetPositions.forEach(p -> {
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data);
}); });
break; break;
case Replace: case Replace:
@ -82,7 +82,7 @@ public enum TerrainTools {
if (isReplaceable(toReplace)) if (isReplaceable(toReplace))
return; return;
world.setBlockState(p, paintedState); world.setBlockState(p, paintedState);
ZapperItem.setTileData(world, p, data); ZapperItem.setTileData(world, p, paintedState, data);
}); });
break; break;
} }

View file

@ -2,7 +2,6 @@ package com.simibubi.create.content.logistics.block.redstone;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; 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.ITE;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;

View file

@ -2,8 +2,11 @@ package com.simibubi.create.content.schematics;
import com.mojang.datafixers.Dynamic; import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.DynamicOps; import com.mojang.datafixers.types.DynamicOps;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorldReader; 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) { public Template.BlockInfo process(IWorldReader world, BlockPos pos, Template.BlockInfo rawInfo, Template.BlockInfo info, PlacementSettings settings, @Nullable Template template) {
if (info.nbt != null) { if (info.nbt != null) {
TileEntity te = info.state.createTileEntity(world); TileEntity te = info.state.createTileEntity(world);
if (te != null && te.onlyOpsCanSetNbt()) { if (te != null) {
return new Template.BlockInfo(info.pos, info.state, null); CompoundNBT nbt = NBTProcessors.process(te, info.nbt, false);
if (nbt != info.nbt)
return new Template.BlockInfo(info.pos, info.state, nbt);
} }
} }
return info; return info;

View file

@ -5,7 +5,6 @@ import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -14,8 +13,6 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create; import com.simibubi.create.Create;

View file

@ -27,6 +27,7 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTProcessors;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -466,8 +467,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
CompoundNBT data = null; CompoundNBT data = null;
if (AllBlockTags.SAFE_NBT.matches(blockState)) { if (AllBlockTags.SAFE_NBT.matches(blockState)) {
TileEntity tile = blockReader.getTileEntity(target); TileEntity tile = blockReader.getTileEntity(target);
if (tile != null && !tile.onlyOpsCanSetNbt()) { if (tile != null) {
data = tile.write(new CompoundNBT()); data = tile.write(new CompoundNBT());
data = NBTProcessors.process(tile, data, true);
} }
} }
launchBlock(target, icon, blockState, data); launchBlock(target, icon, blockState, data);

View file

@ -154,7 +154,7 @@ public class SchematicItem extends Item {
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
if (!onItemUse(playerIn, handIn)) if (!onItemUse(playerIn, handIn))
return super.onItemRightClick(worldIn, playerIn, handIn); return super.onItemRightClick(worldIn, playerIn, handIn);
return new ActionResult<ItemStack>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn)); return new ActionResult<>(ActionResultType.SUCCESS, playerIn.getHeldItem(handIn));
} }
private boolean onItemUse(PlayerEntity player, Hand hand) { private boolean onItemUse(PlayerEntity player, Hand hand) {

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.schematics.packet;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.content.schematics.SchematicProcessor;
import com.simibubi.create.content.schematics.item.SchematicItem; import com.simibubi.create.content.schematics.item.SchematicItem;
import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.networking.SimplePacketBase;
@ -36,6 +37,8 @@ public class SchematicPlacePacket extends SimplePacketBase {
return; return;
Template t = SchematicItem.loadSchematic(stack); Template t = SchematicItem.loadSchematic(stack);
PlacementSettings settings = SchematicItem.getSettings(stack); PlacementSettings settings = SchematicItem.getSettings(stack);
if (player.canUseCommandBlock())
settings.func_215220_b(SchematicProcessor.INSTANCE); // remove processor
settings.setIgnoreEntities(false); settings.setIgnoreEntities(false);
t.addBlocksToWorld(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")), t.addBlocksToWorld(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")),
settings); settings);

View file

@ -5,7 +5,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;

View file

@ -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<TileEntityType<?>, UnaryOperator<CompoundNBT>> processors = new HashMap<>();
private static final Map<TileEntityType<?>, UnaryOperator<CompoundNBT>> survivalProcessors = new HashMap<>();
public static synchronized void addProcessor(TileEntityType<?> type, UnaryOperator<CompoundNBT> processor) {
processors.put(type, processor);
}
public static synchronized void addSurvivalProcessor(TileEntityType<?> type, UnaryOperator<CompoundNBT> 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;
}
}