mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-16 04:13:42 +01:00
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
This commit is contained in:
parent
22ed233969
commit
1b84bbf16f
4 changed files with 254 additions and 61 deletions
|
@ -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<OutlineParams> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<NixieTubeTile
|
|||
setDefaultState(getDefaultState().with(CEILING, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
|
||||
BlockRayTraceResult ray) {
|
||||
try {
|
||||
|
||||
ItemStack heldItem = player.getHeldItem(hand);
|
||||
NixieTubeTileEntity nixie = getTileEntity(world, pos);
|
||||
|
||||
if (player.isSneaking())
|
||||
return ActionResultType.PASS;
|
||||
|
||||
if (heldItem.isEmpty()) {
|
||||
if (nixie.reactsToRedstone())
|
||||
return ActionResultType.PASS;
|
||||
nixie.clearCustomText();
|
||||
updateDisplayedRedstoneValue(state, world, pos);
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
if (heldItem.getItem() == Items.NAME_TAG && heldItem.hasDisplayName()) {
|
||||
Direction left = state.get(HORIZONTAL_FACING)
|
||||
.rotateY();
|
||||
Direction right = left.getOpposite();
|
||||
|
||||
if (world.isRemote)
|
||||
return ActionResultType.SUCCESS;
|
||||
|
||||
BlockPos currentPos = pos;
|
||||
while (true) {
|
||||
BlockPos nextPos = currentPos.offset(left);
|
||||
if (world.getBlockState(nextPos) != state)
|
||||
break;
|
||||
currentPos = nextPos;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
|
||||
while (true) {
|
||||
final int rowPosition = index;
|
||||
withTileEntityDo(world, currentPos, te -> 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<Block, BlockState> builder) {
|
||||
super.fillStateContainer(builder.add(CEILING, HORIZONTAL_FACING));
|
||||
|
@ -57,12 +117,12 @@ public class NixieTubeBlock extends HorizontalBlock implements ITE<NixieTubeTile
|
|||
@Override
|
||||
public void neighborChanged(BlockState p_220069_1_, World p_220069_2_, BlockPos p_220069_3_, Block p_220069_4_,
|
||||
BlockPos p_220069_5_, boolean p_220069_6_) {
|
||||
updateDisplayedValue(p_220069_1_, p_220069_2_, p_220069_3_);
|
||||
updateDisplayedRedstoneValue(p_220069_1_, p_220069_2_, p_220069_3_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||
updateDisplayedValue(state, worldIn, pos);
|
||||
updateDisplayedRedstoneValue(state, worldIn, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,12 +135,13 @@ public class NixieTubeBlock extends HorizontalBlock implements ITE<NixieTubeTile
|
|||
return true;
|
||||
}
|
||||
|
||||
private void updateDisplayedValue(BlockState state, World worldIn, BlockPos pos) {
|
||||
private void updateDisplayedRedstoneValue(BlockState state, World worldIn, BlockPos pos) {
|
||||
if (worldIn.isRemote)
|
||||
return;
|
||||
int power = getPower(worldIn, pos);
|
||||
String display = (power < 10 ? "0" : "") + power;
|
||||
withTileEntityDo(worldIn, pos, te -> 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) {
|
||||
|
|
|
@ -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<NixieTubeTileEntity> {
|
||||
|
||||
Random r = new Random();
|
||||
|
||||
|
||||
public NixieTubeRenderer(TileEntityRendererDispatcher dispatcher) {
|
||||
super(dispatcher);
|
||||
}
|
||||
|
@ -25,64 +26,64 @@ public class NixieTubeRenderer extends SafeTileEntityRenderer<NixieTubeTileEntit
|
|||
@Override
|
||||
protected void renderSafe(NixieTubeTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
|
||||
ms.push();
|
||||
BlockState blockState = te.getBlockState();
|
||||
MatrixStacker.of(ms)
|
||||
.centre()
|
||||
.rotateY(AngleHelper.horizontalAngle(blockState
|
||||
.get(NixieTubeBlock.HORIZONTAL_FACING)));
|
||||
.rotateY(AngleHelper.horizontalAngle(blockState.get(NixieTubeBlock.HORIZONTAL_FACING)));
|
||||
|
||||
float height = blockState.get(NixieTubeBlock.CEILING) ? 2 : 6;
|
||||
float scale = 1 / 20f;
|
||||
|
||||
|
||||
Couple<String> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Pair<ITextComponent, Integer>> customText;
|
||||
JsonElement rawCustomText;
|
||||
Couple<String> 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<ITextComponent, Integer> textSection = customText.get();
|
||||
textSection.setFirst(updateDynamicTextComponents(ITextComponent.Serializer.fromJson(rawCustomText)));
|
||||
|
||||
Couple<String> 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<String> 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<ITextComponent> 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<TileEntityBehaviour> behaviours) {}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue