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:analog_lever",
"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_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.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;

View File

@ -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;

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.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++)

View File

@ -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;

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.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<ItemStack>(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<ItemStack>(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<ItemStack>(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<ItemStack>(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<ItemStack>(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<ItemStack>(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());

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

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.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);

View File

@ -154,7 +154,7 @@ public class SchematicItem extends Item {
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
if (!onItemUse(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) {

View File

@ -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);

View File

@ -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;

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;
}
}