From 1b84bbf16f515d584d84533b2bad3fb7decbb670 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sun, 11 Oct 2020 17:50:48 +0200 Subject: [PATCH] Custom Nixies - Rows of nixie tubes will now display text from a name tag used on them - Nixie tubes will dynamically update score/selector/nbt components in the displayed text --- .../contraptions/fluids/FluidPropagator.java | 29 ++- .../block/redstone/NixieTubeBlock.java | 73 +++++++- .../block/redstone/NixieTubeRenderer.java | 39 ++-- .../block/redstone/NixieTubeTileEntity.java | 174 ++++++++++++++++-- 4 files changed, 254 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java index 066750b38..5ffc2e22e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java @@ -8,7 +8,6 @@ import java.util.Set; import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.AllBlocks; -import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock; import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; import com.simibubi.create.foundation.config.AllConfigs; @@ -27,13 +26,10 @@ import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fml.DistExecutor; public class FluidPropagator { @@ -136,20 +132,21 @@ public class FluidPropagator { return AllConfigs.SERVER.fluids.mechanicalPumpRange.get(); } + @Deprecated // Remove after pipes are fixed; comment out for production public static OutlineParams showBlockFace(BlockFace face) { MutableObject params = new MutableObject<>(new OutlineParams()); - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { - Vec3d directionVec = new Vec3d(face.getFace() - .getDirectionVec()); - Vec3d scaleVec = directionVec.scale(-.25f * face.getFace() - .getAxisDirection() - .getOffset()); - directionVec = directionVec.scale(.5f); - params.setValue(CreateClient.outliner.showAABB(face, - FluidPropagator.smallCenter.offset(directionVec.add(new Vec3d(face.getPos()))) - .grow(scaleVec.x, scaleVec.y, scaleVec.z) - .grow(1 / 16f))); - }); +// DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { +// Vec3d directionVec = new Vec3d(face.getFace() +// .getDirectionVec()); +// Vec3d scaleVec = directionVec.scale(-.25f * face.getFace() +// .getAxisDirection() +// .getOffset()); +// directionVec = directionVec.scale(.5f); +// params.setValue(CreateClient.outliner.showAABB(face, +// FluidPropagator.smallCenter.offset(directionVec.add(new Vec3d(face.getPos()))) +// .grow(scaleVec.x, scaleVec.y, scaleVec.z) +// .grow(1 / 16f))); +// }); return params.getValue(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java index 0efc5957e..fcd47f20d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java @@ -8,12 +8,18 @@ import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.HorizontalBlock; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.state.BooleanProperty; import net.minecraft.state.StateContainer.Builder; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; +import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; @@ -29,6 +35,60 @@ public class NixieTubeBlock extends HorizontalBlock implements ITE te.displayCustomNameOf(heldItem, rowPosition)); + BlockPos nextPos = currentPos.offset(right); + if (world.getBlockState(nextPos) != state) + break; + currentPos = nextPos; + index++; + } + } + + } catch (TileEntityException e) { + } + + return ActionResultType.PASS; + } + @Override protected void fillStateContainer(Builder builder) { super.fillStateContainer(builder.add(CEILING, HORIZONTAL_FACING)); @@ -57,12 +117,12 @@ public class NixieTubeBlock extends HorizontalBlock implements ITE te.display(display.charAt(0), display.charAt(1))); + withTileEntityDo(worldIn, pos, te -> { + if (te.reactsToRedstone()) + te.displayRedstoneStrength(getPower(worldIn, pos)); + }); } static boolean isValidBlock(IBlockReader world, BlockPos pos, boolean above) { diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeRenderer.java index 5993f4d04..d755f709f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeRenderer.java @@ -6,6 +6,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.block.BlockState; @@ -17,7 +18,7 @@ import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; public class NixieTubeRenderer extends SafeTileEntityRenderer { Random r = new Random(); - + public NixieTubeRenderer(TileEntityRendererDispatcher dispatcher) { super(dispatcher); } @@ -25,64 +26,64 @@ public class NixieTubeRenderer extends SafeTileEntityRenderer s = te.getVisibleText(); + ms.push(); - ms.translate(-4/16f, 0, 0); + ms.translate(-4 / 16f, 0, 0); ms.scale(scale, -scale, scale); - drawTube(ms, buffer, te.tube1, height); + drawTube(ms, buffer, s.getFirst(), height); ms.pop(); - + ms.push(); - ms.translate(4/16f, 0, 0); + ms.translate(4 / 16f, 0, 0); ms.scale(scale, -scale, scale); - drawTube(ms, buffer, te.tube2, height); + drawTube(ms, buffer, s.getSecond(), height); ms.pop(); ms.pop(); } - private void drawTube(MatrixStack ms, IRenderTypeBuffer buffer, char c, float height) { + private void drawTube(MatrixStack ms, IRenderTypeBuffer buffer, String c, float height) { FontRenderer fontRenderer = Minecraft.getInstance().fontRenderer; - float charWidth = fontRenderer.getCharWidth(c); + float charWidth = fontRenderer.getStringWidth(c); float shadowOffset = .5f; float flicker = r.nextFloat(); int brightColor = 0xFF982B; int darkColor = 0xE03221; int flickeringBrightColor = ColorHelper.mixColors(brightColor, darkColor, flicker / 4); - + ms.push(); ms.translate((charWidth - shadowOffset) / -2f, -height, 0); drawChar(ms, buffer, c, flickeringBrightColor); ms.push(); - ms.translate(shadowOffset, shadowOffset, -1/16f); + ms.translate(shadowOffset, shadowOffset, -1 / 16f); drawChar(ms, buffer, c, darkColor); ms.pop(); ms.pop(); - + ms.push(); ms.scale(-1, 1, 1); ms.translate((charWidth - shadowOffset) / -2f, -height, 0); drawChar(ms, buffer, c, darkColor); ms.push(); - ms.translate(-shadowOffset, shadowOffset, -1/16f); + ms.translate(-shadowOffset, shadowOffset, -1 / 16f); drawChar(ms, buffer, c, 0x99180F); ms.pop(); ms.pop(); } - - private static void drawChar(MatrixStack ms, IRenderTypeBuffer buffer, char c, int color) { + + private static void drawChar(MatrixStack ms, IRenderTypeBuffer buffer, String c, int color) { FontRenderer fontRenderer = Minecraft.getInstance().fontRenderer; - fontRenderer.draw(String.valueOf(c), 0, 0, color, false, ms.peek() + fontRenderer.draw(c, 0, 0, color, false, ms.peek() .getModel(), buffer, false, 0, 15728880); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeTileEntity.java index a8d7ac454..6505de9dc 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeTileEntity.java @@ -1,41 +1,175 @@ package com.simibubi.create.content.logistics.block.redstone; -import com.simibubi.create.foundation.tileEntity.SyncedTileEntity; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import javax.annotation.Nullable; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.command.CommandSource; +import net.minecraft.command.ICommandSource; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextComponentUtils; +import net.minecraft.world.server.ServerWorld; -public class NixieTubeTileEntity extends SyncedTileEntity { +public class NixieTubeTileEntity extends SmartTileEntity { - char tube1; - char tube2; + Optional> customText; + JsonElement rawCustomText; + Couple renderText; + + int redstoneStrength; public NixieTubeTileEntity(TileEntityType tileEntityTypeIn) { super(tileEntityTypeIn); - tube1 = '0'; - tube2 = '0'; + redstoneStrength = 0; + customText = Optional.empty(); } @Override - public CompoundNBT write(CompoundNBT nbt) { - super.write(nbt); - nbt.putInt("tube1", tube1); - nbt.putInt("tube2", tube2); - return nbt; + public void tick() { + super.tick(); + + // Dynamic text components have to be ticked manually and re-sent to the client + if (customText.isPresent() && world instanceof ServerWorld) { + Pair textSection = customText.get(); + textSection.setFirst(updateDynamicTextComponents(ITextComponent.Serializer.fromJson(rawCustomText))); + + Couple currentText = getVisibleText(); + if (renderText != null && renderText.equals(currentText)) + return; + + renderText = currentText; + sendData(); + } } - public void display(char tube1, char tube2) { - this.tube1 = tube1; - this.tube2 = tube2; - markDirty(); - sendData(); + // + + public void clearCustomText() { + if (!customText.isPresent()) + return; + displayRedstoneStrength(0); + } + + public void displayCustomNameOf(ItemStack stack, int nixiePositionInRow) { + CompoundNBT compoundnbt = stack.getChildTag("display"); + if (compoundnbt != null && compoundnbt.contains("Name", 8)) { + JsonElement fromJson = getJsonFromString(compoundnbt.getString("Name")); + ITextComponent displayed = ITextComponent.Serializer.fromJson(fromJson); + if (this.world instanceof ServerWorld) + displayed = updateDynamicTextComponents(displayed); + this.customText = Optional.of(Pair.of(displayed, nixiePositionInRow)); + this.rawCustomText = fromJson; + notifyUpdate(); + } + } + + public void displayRedstoneStrength(int signalStrength) { + customText = Optional.empty(); + redstoneStrength = signalStrength; + notifyUpdate(); + } + + public boolean reactsToRedstone() { + return !customText.isPresent(); + } + + public Couple getVisibleText() { + if (!customText.isPresent()) + return Couple.create(redstoneStrength < 10 ? "0" : "1", redstoneStrength % 10 + ""); + String fullText = createStringFromComponentText(customText.get() + .getFirst()); + int index = customText.get() + .getSecond() * 2; + return Couple.create(charOrEmpty(fullText, index), charOrEmpty(fullText, index + 1)); + } + + // + + @Override + protected void read(CompoundNBT nbt, boolean clientPacket) { + customText = Optional.empty(); + redstoneStrength = nbt.getInt("RedstoneStrength"); + if (nbt.contains("CustomText")) { + ITextComponent displayed = ITextComponent.Serializer.fromJson(nbt.getString("CustomText")); + rawCustomText = getJsonFromString(nbt.getString("RawCustomText")); + customText = Optional.of(Pair.of(displayed, nbt.getInt("CustomTextIndex"))); + } + super.read(nbt, clientPacket); } @Override - public void read(CompoundNBT nbt) { - tube1 = (char) nbt.getInt("tube1"); - tube2 = (char) nbt.getInt("tube2"); - super.read(nbt); + protected void write(CompoundNBT nbt, boolean clientPacket) { + super.write(nbt, clientPacket); + nbt.putInt("RedstoneStrength", redstoneStrength); + + if (customText.isPresent()) { + nbt.putString("RawCustomText", rawCustomText.toString()); + nbt.putString("CustomText", ITextComponent.Serializer.toJson(customText.get() + .getFirst())); + nbt.putInt("CustomTextIndex", customText.get() + .getSecond()); + } } + private JsonElement getJsonFromString(String string) { + return new JsonParser().parse(string); + } + + protected ITextComponent updateDynamicTextComponents(ITextComponent customText) { + try { + return TextComponentUtils.updateForEntity(this.getCommandSource((ServerPlayerEntity) null), customText, + (Entity) null, 0); + } catch (CommandSyntaxException e) { + } + return customText; + } + + // From SignTileEntity + protected CommandSource getCommandSource(@Nullable ServerPlayerEntity p_195539_1_) { + String s = p_195539_1_ == null ? "Sign" + : p_195539_1_.getName() + .getString(); + ITextComponent itextcomponent = + (ITextComponent) (p_195539_1_ == null ? new StringTextComponent("Sign") : p_195539_1_.getDisplayName()); + return new CommandSource(ICommandSource.field_213139_a_, + new Vec3d((double) this.pos.getX() + 0.5D, (double) this.pos.getY() + 0.5D, + (double) this.pos.getZ() + 0.5D), + Vec2f.ZERO, (ServerWorld) this.world, 2, s, itextcomponent, this.world.getServer(), p_195539_1_); + } + + protected String createStringFromComponentText(ITextComponent iTextComponent) { + StringBuilder stringbuilder = new StringBuilder(); + Iterator iterator = iTextComponent.stream() + .iterator(); + while (iterator.hasNext()) + stringbuilder.append(iterator.next() + .getUnformattedComponentText()); + return stringbuilder.toString(); + } + + private String charOrEmpty(String string, int index) { + return string.length() <= index ? " " : string.substring(index, index + 1); + } + + @Override + public void addBehaviours(List behaviours) {} + }