Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
"text.extended_industrialization.key_mouse_scroll": "Mouse Scroll",
"text.extended_industrialization.machine_batcher_coils": "Batch size and cost is determined by coil used.",
"text.extended_industrialization.machine_chainer_connected_machines": "Connected Machines: %d / %d",
"text.extended_industrialization.machine_chainer_help_1": "Connects up to %d consecutive machines in a horizontal line in the direction it is facing.",
"text.extended_industrialization.machine_chainer_help_1": "Connects up to %d consecutive machines in a straight line in the direction it is facing.",
"text.extended_industrialization.machine_chainer_help_2": "Accepts items, fluids, and energy and distributes them to connected machines.",
"text.extended_industrialization.machine_chainer_help_3": "Can connect to other machine chainers, but it must not link back to itself.",
"text.extended_industrialization.machine_chainer_problem_at": "Problem at: %s",
Expand Down Expand Up @@ -192,4 +192,4 @@
"text.extended_industrialization.universal_transformer_from_tier_input": "Hull for cable tier to convert from (LV by default).",
"text.extended_industrialization.universal_transformer_to_tier_input": "Hull for cable tier to convert to (LV by default).",
"text.extended_industrialization.waste_collector_help": "When placed underneath animals, manure will be collected."
}
}
36 changes: 17 additions & 19 deletions src/main/java/net/swedz/extended_industrialization/EIClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import aztech.modern_industrialization.machines.multiblocks.MultiblockTankBER;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
Expand All @@ -24,14 +25,16 @@
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.ClientTickEvent;
import net.neoforged.neoforge.client.event.InputEvent;
import net.neoforged.neoforge.client.event.ModelEvent;
import net.neoforged.neoforge.client.event.RegisterClientTooltipComponentFactoriesEvent;
import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent;
import net.neoforged.neoforge.client.event.RegisterGuiLayersEvent;
import net.neoforged.neoforge.client.gui.VanillaGuiLayers;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.swedz.extended_industrialization.client.MachineChainerHighlightRenderer;
import net.swedz.extended_industrialization.client.NanoGravichestplateHudRenderer;
import net.swedz.extended_industrialization.client.ber.chainer.MachineChainerHighlightRenderer;
import net.swedz.extended_industrialization.client.model.chainer.MachineChainerUnbakedModel;
import net.swedz.extended_industrialization.item.ElectricToolItem;
import net.swedz.extended_industrialization.item.SteamChainsawItem;
import net.swedz.extended_industrialization.item.machineconfig.MachineConfigCardItem;
Expand Down Expand Up @@ -94,9 +97,12 @@ private static void onRegisterColorItems(RegisterColorHandlersEvent.Item event)
);
}

/**
* Taken from {@link aztech.modern_industrialization.MIClient#registerBlockEntityRenderers(FMLClientSetupEvent)}. This is needed to make multiblocks render their layout when holding a wrench.
*/
@SubscribeEvent
private static void registerModelLoaders(ModelEvent.RegisterGeometryLoaders event)
{
event.register(MachineChainerUnbakedModel.LOADER_ID, MachineChainerUnbakedModel.LOADER);
}

@SubscribeEvent
private static void registerBlockEntityRenderers(FMLClientSetupEvent event)
{
Expand All @@ -107,22 +113,14 @@ private static void registerBlockEntityRenderers(FMLClientSetupEvent event)
MachineBlockEntity blockEntity = machine.getBlockEntityInstance();
BlockEntityType type = blockEntity.getType();

if(blockEntity instanceof LargeTankMultiblockBlockEntity)
{
BlockEntityRenderers.register(type, MultiblockTankBER::new);
}
else if(blockEntity instanceof MultiblockMachineBlockEntity)
BlockEntityRendererProvider provider = switch (blockEntity)
{
BlockEntityRenderers.register(type, MultiblockMachineBER::new);
}
else if(blockEntity instanceof MachineChainerMachineBlockEntity)
{
BlockEntityRenderers.register(type, MachineChainerHighlightRenderer::new);
}
else
{
BlockEntityRenderers.register(type, (c) -> new MachineBlockEntityRenderer<>(c));
}
case MachineChainerMachineBlockEntity be -> MachineChainerHighlightRenderer::new;
case LargeTankMultiblockBlockEntity be -> MultiblockTankBER::new;
case MultiblockMachineBlockEntity be -> MultiblockMachineBER::new;
default -> MachineBlockEntityRenderer::new;
};
BlockEntityRenderers.register(type, provider);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public enum EIText implements MICompatibleTranslatableTextEnum
KEY_MOUSE_SCROLL("Mouse Scroll"),
MACHINE_BATCHER_COILS("Batch size and cost is determined by coil used."),
MACHINE_CHAINER_CONNECTED_MACHINES("Connected Machines: %d / %d"),
MACHINE_CHAINER_HELP_1("Connects up to %d consecutive machines in a horizontal line in the direction it is facing."),
MACHINE_CHAINER_HELP_1("Connects up to %d consecutive machines in a straight line in the direction it is facing."),
MACHINE_CHAINER_HELP_2("Accepts items, fluids, and energy and distributes them to connected machines."),
MACHINE_CHAINER_HELP_3("Can connect to other machine chainers, but it must not link back to itself."),
MACHINE_CHAINER_PROBLEM_AT("Problem at: %s"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package net.swedz.extended_industrialization.client.ber.chainer;

import aztech.modern_industrialization.compat.sodium.SodiumCompat;
import aztech.modern_industrialization.machines.models.MachineModelClientData;
import aztech.modern_industrialization.util.ModelHelper;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.BlockModelShaper;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.client.model.pipeline.QuadBakingVertexConsumer;
import net.swedz.extended_industrialization.EI;
import net.swedz.extended_industrialization.client.model.chainer.MachineChainerBakedModel;
import net.swedz.extended_industrialization.machines.blockentity.MachineChainerMachineBlockEntity;

/**
* Based on {@link aztech.modern_industrialization.machines.MachineBlockEntityRenderer}
*/
public sealed class MachineChainerBlockEntityRenderer implements BlockEntityRenderer<MachineChainerMachineBlockEntity> permits MachineChainerHighlightRenderer
{
private final BlockModelShaper blockModels;
private BlockState lastBlockState = null;
private MachineChainerBakedModel model = null;
private final Object[] quadCache = new Object[36];
private static final Object NO_QUAD = new Object();

public MachineChainerBlockEntityRenderer(BlockEntityRendererProvider.Context context)
{
blockModels = context.getBlockRenderDispatcher().getBlockModelShaper();
}

private BakedQuad getCachedQuad(MachineModelClientData data, Direction direction)
{
var facing = data.frontDirection;
int cachedQuadIndex = facing.ordinal() * 6 + direction.ordinal();

if(quadCache[cachedQuadIndex] == null)
{
TextureAtlasSprite sprite = model == null ? null : MachineChainerBakedModel.getSprite(model.getSprites(), direction, facing, true);
if(sprite != null)
{
var vc = new QuadBakingVertexConsumer();
quadCache[cachedQuadIndex] = ModelHelper.bakeSprite(vc, direction, sprite, -2 * MachineChainerBakedModel.Z_OFFSET);
}
else
{
quadCache[cachedQuadIndex] = NO_QUAD;
}
}

var quad = quadCache[cachedQuadIndex];
return quad == NO_QUAD ? null : (BakedQuad) quad;
}

private MachineChainerBakedModel getMachineModel(BlockState state)
{
if(blockModels.getBlockModel(state) instanceof MachineChainerBakedModel mbm)
{
return mbm;
}
else
{
EI.LOGGER.warn("Model {} should have been a MachineChainerBakedModel, but was {}", state, blockModels.getBlockModel(state).getClass());
return null;
}
}

@Override
public void render(MachineChainerMachineBlockEntity machine, float tickDelta, PoseStack matrices, MultiBufferSource buffer, int light, int overlay)
{
BlockState state = machine.getBlockState();
if(lastBlockState == null)
{
lastBlockState = state;
model = this.getMachineModel(state);
}
else if(lastBlockState != state)
{
throw new IllegalStateException("Tried to use the same machine BER with two block states: " + state + " and " + lastBlockState);
}

MachineModelClientData data = machine.getMachineModelData();
if(data.isActive)
{
VertexConsumer vc = buffer.getBuffer(Sheets.cutoutBlockSheet());

for(Direction direction : Direction.values())
{
BakedQuad quad = this.getCachedQuad(data, direction);
if(quad != null)
{
int faceLight = LevelRenderer.getLightColor(machine.getLevel(), machine.getBlockState(), machine.getBlockPos().relative(direction));
vc.putBulkData(matrices.last(), quad, 1.0f, 1.0f, 1.0f, 1.0f, faceLight, OverlayTexture.NO_OVERLAY);

SodiumCompat.markSpriteActive(quad.getSprite());
}
}
}
}

@Override
public int getViewDistance()
{
return 256;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package net.swedz.extended_industrialization.client;
package net.swedz.extended_industrialization.client.ber.chainer;

import aztech.modern_industrialization.MITags;
import aztech.modern_industrialization.machines.MachineBlockEntityRenderer;
import aztech.modern_industrialization.util.RenderHelper;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
Expand All @@ -17,7 +16,7 @@
import net.swedz.extended_industrialization.machines.blockentity.MachineChainerMachineBlockEntity;
import net.swedz.extended_industrialization.machines.component.chainer.ChainerLinks;

public final class MachineChainerHighlightRenderer extends MachineBlockEntityRenderer<MachineChainerMachineBlockEntity>
public final class MachineChainerHighlightRenderer extends MachineChainerBlockEntityRenderer
{
private static final int COLOR_SUCCESS = 0x6FFF6F;
private static final int COLOR_FAILURE = 0xFF6F6F;
Expand Down Expand Up @@ -130,20 +129,40 @@ private void renderPosition(MachineChainerMachineBlockEntity machine, float tick

private Direction pickNumberRenderFace(MachineChainerMachineBlockEntity machine)
{
int playerY = Minecraft.getInstance().player.blockPosition().getY();
int machineY = machine.getBlockPos().getY();
int playerY = (int) Math.round(Minecraft.getInstance().player.getY());

if(playerY == machineY || playerY == machineY - 1)
Direction machineDirection = machine.orientation.facingDirection;
if(machineDirection.getAxis().isHorizontal())
{
return Direction.fromYRot(Minecraft.getInstance().player.yHeadRot).getOpposite();
}
else if(playerY < machineY)
{
return Direction.DOWN;
int machineY = machine.getBlockPos().getY();

if(playerY == machineY || playerY == machineY - 1)
{
return Direction.fromYRot(Minecraft.getInstance().player.yHeadRot).getOpposite();
}
else if(playerY < machineY)
{
return Direction.DOWN;
}
else
{
return Direction.UP;
}
}
else
{
return Direction.UP;
int machineEndY = machine.getChainerComponent().links().positionAfter().getY();

if(machineDirection == Direction.UP && playerY >= machineEndY)
{
return Direction.UP;
}
else if(machineDirection == Direction.DOWN && playerY < machineEndY)
{
return Direction.DOWN;
}

return Direction.fromYRot(Minecraft.getInstance().player.yHeadRot).getOpposite();
}
}

Expand All @@ -157,21 +176,32 @@ private String pickArrowSymbol(MachineChainerMachineBlockEntity machine,
Direction playerDirectionRight = playerDirection.getClockWise();

String arrow = "";
if(playerDirection == machineDirection)
if(renderDirection != machineDirection && renderDirection != machineDirection.getOpposite())
{
arrow = renderDirection == Direction.DOWN ? ARROW_DOWN : ARROW_UP;
}
else if(playerDirection == machineDirection.getOpposite())
{
arrow = renderDirection == Direction.DOWN ? ARROW_UP : ARROW_DOWN;
}
else if(playerDirectionLeft == machineDirection)
{
arrow = ARROW_LEFT;
}
else if(playerDirectionRight == machineDirection)
{
arrow = ARROW_RIGHT;
if(playerDirection == machineDirection)
{
arrow = renderDirection == Direction.DOWN ? ARROW_DOWN : ARROW_UP;
}
else if(playerDirection == machineDirection.getOpposite())
{
arrow = renderDirection == Direction.DOWN ? ARROW_UP : ARROW_DOWN;
}
else if(playerDirectionLeft == machineDirection)
{
arrow = ARROW_LEFT;
}
else if(playerDirectionRight == machineDirection)
{
arrow = ARROW_RIGHT;
}
else if(machineDirection == Direction.UP)
{
arrow = ARROW_UP;
}
else if(machineDirection == Direction.DOWN)
{
arrow = ARROW_DOWN;
}
}
return arrow;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package net.swedz.extended_industrialization.client.model;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import net.minecraft.client.resources.model.Material;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;

import java.lang.reflect.Field;

public interface MachineOverlaysJson
{
Material[] toSpriteIds();

int[] getOutputSpriteIndexes();

Gson GSON = new GsonBuilder().registerTypeAdapter(ResourceLocation.class, new ResourceLocation.Serializer()).create();

static <O extends MachineOverlaysJson> O parse(Class<O> clazz, JsonObject json, MachineOverlaysJson defaultOverlay)
{
O overlays = GSON.fromJson(json, clazz);

if(defaultOverlay != null)
{
try
{
for(Field field : clazz.getDeclaredFields())
{
if(field.get(overlays) == null)
{
field.set(overlays, field.get(defaultOverlay));
}
}
}
catch (IllegalAccessException ex)
{
throw new RuntimeException("Failed to copy fields from default overlay", ex);
}
}

return overlays;
}

default Material select(ResourceLocation... candidates)
{
for(ResourceLocation id : candidates)
{
if(id != null)
{
return new Material(InventoryMenu.BLOCK_ATLAS, id);
}
}
return null;
}
}
Loading