Big lathe
This commit is contained in:
@@ -10,6 +10,7 @@ import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@@ -71,6 +72,8 @@ public class IBG {
|
||||
var latheDef = GTRegistries.MACHINES.get(
|
||||
ResourceLocation.fromNamespaceAndPath("gtceu", "lv_lathe"));
|
||||
|
||||
latheDef.setShape(Block.box(-16, 0, 0, 32-16, 14, 16));
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
BlockEntityRendererProvider<BlockEntity> provider = (BlockEntityRendererProvider) (ctx -> new AnimatedBlockRenderer<>(
|
||||
ctx));
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.imbgt.ibg.block;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.imbgt.ibg.IBG;
|
||||
import com.imbgt.ibg.block.custom.AnimatedBlock;
|
||||
import com.imbgt.ibg.block.custom.PartBlock;
|
||||
import com.imbgt.ibg.item.ModItems;
|
||||
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
@@ -20,13 +19,11 @@ public class ModBlocks {
|
||||
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, IBG.MOD_ID);
|
||||
|
||||
public static final RegistryObject<Block> ANIMATED_BLOCK = BLOCKS.register("animated_block",
|
||||
() -> new AnimatedBlock(BlockBehaviour.Properties.copy(Blocks.IRON_BLOCK).noOcclusion()));
|
||||
() -> new AnimatedBlock(BlockBehaviour.Properties.copy(Blocks.IRON_BLOCK).noOcclusion()));
|
||||
|
||||
private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block) {
|
||||
RegistryObject<T> toReturn = BLOCKS.register(name, block);
|
||||
registerBlockItem(name, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
public static final RegistryObject<Block> PART = BLOCKS.register(
|
||||
"part",
|
||||
() -> new PartBlock(BlockBehaviour.Properties.of().noOcclusion().strength(2.0F)));
|
||||
|
||||
private static <T extends Block> RegistryObject<Item> registerBlockItem(String name, RegistryObject<T> block) {
|
||||
return ModItems.ITEMS_REGISTER.register(name, () -> new BlockItem(block.get(), new Item.Properties()));
|
||||
|
||||
96
src/main/java/com/imbgt/ibg/block/custom/PartBlock.java
Normal file
96
src/main/java/com/imbgt/ibg/block/custom/PartBlock.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package com.imbgt.ibg.block.custom;
|
||||
|
||||
import com.imbgt.ibg.block.entity.PartBE;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
public class PartBlock extends Block implements EntityBlock {
|
||||
public PartBlock(Properties p) {
|
||||
super(p.noOcclusion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState st) {
|
||||
return new PartBE(pos, st);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(BlockState st, Level lvl, BlockPos pos,
|
||||
Player pl, InteractionHand hand, BlockHitResult hit) {
|
||||
if (lvl.isClientSide) {
|
||||
// Let the hand animate; the server will run the real logic.
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
BlockEntity be = lvl.getBlockEntity(pos);
|
||||
if (!(be instanceof PartBE part))
|
||||
return InteractionResult.PASS;
|
||||
|
||||
BlockPos masterPos = part.getMaster();
|
||||
if (masterPos == null)
|
||||
return InteractionResult.PASS;
|
||||
|
||||
BlockState mst = lvl.getBlockState(masterPos);
|
||||
return mst.getBlock().use(mst, lvl, masterPos, pl, hand, hit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderShape getRenderShape(BlockState state) {
|
||||
return RenderShape.INVISIBLE;
|
||||
}
|
||||
|
||||
// Optional: give the part a slice-shaped outline/collision on its own cell
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState s, net.minecraft.world.level.BlockGetter g, BlockPos p,
|
||||
net.minecraft.world.phys.shapes.CollisionContext c) {
|
||||
// Example: the right-hand slice of a 2-wide machine (16..32 on X within this
|
||||
// cell)
|
||||
return Block.box(0, 0, 0, 16, 16, 16); // or custom slice if you want
|
||||
}
|
||||
|
||||
// When the part is broken, break the master (optional, but common)
|
||||
@Override
|
||||
public void playerWillDestroy(Level lvl, BlockPos pos, BlockState st, Player pl) {
|
||||
BlockEntity be = lvl.getBlockEntity(pos);
|
||||
if (!lvl.isClientSide && be instanceof PartBE part && part.getMaster() != null) {
|
||||
BlockPos master = part.getMaster();
|
||||
lvl.setBlock(pos, Blocks.AIR.defaultBlockState(),
|
||||
Block.UPDATE_CLIENTS | Block.UPDATE_KNOWN_SHAPE | Block.UPDATE_SUPPRESS_DROPS);
|
||||
boolean drop = !pl.isCreative();
|
||||
lvl.destroyBlock(master, drop, pl);
|
||||
}
|
||||
super.playerWillDestroy(lvl, pos, st, pl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeClient(
|
||||
java.util.function.Consumer<net.minecraftforge.client.extensions.common.IClientBlockExtensions> consumer) {
|
||||
consumer.accept(new net.minecraftforge.client.extensions.common.IClientBlockExtensions() {
|
||||
|
||||
@Override
|
||||
public boolean addDestroyEffects(BlockState state, Level level, BlockPos pos,
|
||||
net.minecraft.client.particle.ParticleEngine engine) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addHitEffects(BlockState state, Level level, net.minecraft.world.phys.HitResult target,
|
||||
net.minecraft.client.particle.ParticleEngine engine) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,10 @@ public class ModBlockEntities {
|
||||
.register("animated_block_entity", () -> BlockEntityType.Builder.of(AnimatedBlockEntity::new,
|
||||
ModBlocks.ANIMATED_BLOCK.get()).build(null));
|
||||
|
||||
public static final RegistryObject<BlockEntityType<PartBE>> PART_BE = BLOCK_ENTITIES.register("part",
|
||||
() -> BlockEntityType.Builder.of(PartBE::new, ModBlocks.PART.get())
|
||||
.build(null));
|
||||
|
||||
public static void register(IEventBus eventBus) {
|
||||
BLOCK_ENTITIES.register(eventBus);
|
||||
}
|
||||
|
||||
48
src/main/java/com/imbgt/ibg/block/entity/PartBE.java
Normal file
48
src/main/java/com/imbgt/ibg/block/entity/PartBE.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.imbgt.ibg.block.entity;
|
||||
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class PartBE extends BlockEntity {
|
||||
private BlockPos master;
|
||||
public PartBE(BlockPos pos, BlockState st) { super(ModBlockEntities.PART_BE.get(), pos, st); }
|
||||
public void setMaster(@Nullable BlockPos m) {
|
||||
this.master = m;
|
||||
setChanged();
|
||||
if (level != null && !level.isClientSide) {
|
||||
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable public BlockPos getMaster() { return master; }
|
||||
|
||||
// ---- persistent NBT ----
|
||||
@Override protected void saveAdditional(CompoundTag tag) {
|
||||
super.saveAdditional(tag);
|
||||
if (master != null) tag.putLong("Master", master.asLong());
|
||||
}
|
||||
@Override public void load(CompoundTag tag) {
|
||||
super.load(tag);
|
||||
master = tag.contains("Master") ? BlockPos.of(tag.getLong("Master")) : null;
|
||||
}
|
||||
|
||||
// ---- network sync (server → client) ----
|
||||
@Override public CompoundTag getUpdateTag() {
|
||||
CompoundTag tag = super.getUpdateTag();
|
||||
saveAdditional(tag);
|
||||
return tag;
|
||||
}
|
||||
@Override public void handleUpdateTag(CompoundTag tag) {
|
||||
load(tag);
|
||||
}
|
||||
@Override public @Nullable ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
package com.imbgt.ibg.mixin;
|
||||
|
||||
import com.gregtechceu.gtceu.api.block.AppearanceBlock;
|
||||
import com.gregtechceu.gtceu.api.block.IMachineBlock;
|
||||
import com.gregtechceu.gtceu.api.block.MetaMachineBlock;
|
||||
import com.gregtechceu.gtceu.api.data.RotationState;
|
||||
import com.gregtechceu.gtceu.api.machine.MachineDefinition;
|
||||
import com.imbgt.ibg.IBG;
|
||||
import com.imbgt.ibg.block.ModBlocks;
|
||||
import com.imbgt.ibg.block.entity.PartBE;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
@@ -16,6 +22,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(MetaMachineBlock.class)
|
||||
@@ -30,20 +37,88 @@ public abstract class MetaMachineBlockMixin extends AppearanceBlock {
|
||||
|
||||
@Inject(method = "getRenderShape", at = @At("HEAD"), cancellable = true)
|
||||
private void gtceu$forceAnimatedRender(BlockState state, CallbackInfoReturnable<RenderShape> cir) {
|
||||
|
||||
// Whitelist: only override for the LV lathe
|
||||
if (getDefinition().getId().toString().equals("gtceu:lv_lathe")) {
|
||||
IBG.LOGGER.info("MIXING IT IN");
|
||||
cir.setReturnValue(RenderShape.ENTITYBLOCK_ANIMATED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getOcclusionShape(BlockState state, BlockGetter level, BlockPos pos) {
|
||||
var id = getDefinition().getId();
|
||||
if ("gtceu".equals(id.getNamespace()) && "lv_lathe".equals(id.getPath())) {
|
||||
if (getDefinition().getId().toString().equals("gtceu:lv_lathe")) {
|
||||
return Shapes.empty(); // equivalent to Properties.noOcclusion()
|
||||
}
|
||||
return super.getOcclusionShape(state, level, pos);
|
||||
}
|
||||
|
||||
@Inject(method = "getStateForPlacement", at = @At("HEAD"), cancellable = true)
|
||||
private void ibg$latheFootprintCheck(BlockPlaceContext ctx,
|
||||
CallbackInfoReturnable<BlockState> cir) {
|
||||
MetaMachineBlock self = (MetaMachineBlock) (Object) this;
|
||||
var id = self.getDefinition().getId();
|
||||
if (!("gtceu".equals(id.getNamespace()) && "lv_lathe".equals(id.getPath())))
|
||||
return;
|
||||
|
||||
Level level = ctx.getLevel();
|
||||
BlockPos base = ctx.getClickedPos();
|
||||
|
||||
// Determine facing like MetaMachineBlock does:
|
||||
Direction facing;
|
||||
var rot = self.getDefinition().getRotationState();
|
||||
if (rot == RotationState.Y_AXIS)
|
||||
facing = Direction.UP; // adjust if needed
|
||||
else
|
||||
facing = ctx.getHorizontalDirection().getOpposite();
|
||||
|
||||
// Your footprint: master + one part at +clockwise (adjust if your model
|
||||
// differs)
|
||||
BlockPos partPos = base.relative(facing.getCounterClockWise());
|
||||
|
||||
// If the part cell cannot be replaced => CANCEL placement
|
||||
if (!level.getBlockState(partPos).canBeReplaced(ctx)) {
|
||||
cir.setReturnValue(null); // makes placement fail cleanly
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onPlace", at = @At("TAIL"))
|
||||
private void ibg$placePart(BlockState st, Level lvl, BlockPos pos, BlockState old, boolean moved, CallbackInfo ci) {
|
||||
if (lvl.isClientSide)
|
||||
return;
|
||||
var def = getDefinition().getId();
|
||||
if (!("gtceu".equals(def.getNamespace()) && "lv_lathe".equals(def.getPath())))
|
||||
return;
|
||||
|
||||
var rot = ((IMachineBlock) (Object) this).getRotationState();
|
||||
var facing = rot == RotationState.NONE ? Direction.NORTH : st.getValue(rot.property);
|
||||
|
||||
// Example footprint: extend one cell to +X relative to facing (adjust as
|
||||
// needed)
|
||||
BlockPos partPos = pos.relative(facing.getCounterClockWise());
|
||||
|
||||
if (lvl.getBlockState(partPos).canBeReplaced()) {
|
||||
lvl.setBlockAndUpdate(partPos, ModBlocks.PART.get().defaultBlockState());
|
||||
var be = lvl.getBlockEntity(partPos);
|
||||
if (be instanceof PartBE part)
|
||||
part.setMaster(pos);
|
||||
} else {
|
||||
// Optional: rollback place if you require free space
|
||||
// lvl.removeBlock(pos, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "onRemove", at = @At("HEAD"))
|
||||
private void ibg$removePart(BlockState st, Level lvl, BlockPos pos, BlockState newState, boolean moving,
|
||||
CallbackInfo ci) {
|
||||
if (lvl.isClientSide || st.getBlock() == newState.getBlock())
|
||||
return;
|
||||
var def = getDefinition().getId();
|
||||
if (!("gtceu".equals(def.getNamespace()) && "lv_lathe".equals(def.getPath())))
|
||||
return;
|
||||
|
||||
var rot = ((IMachineBlock) (Object) this).getRotationState();
|
||||
var facing = rot == RotationState.NONE ? Direction.NORTH : st.getValue(rot.property);
|
||||
BlockPos partPos = pos.relative(facing.getCounterClockWise());
|
||||
|
||||
if (lvl.getBlockState(partPos).is(ModBlocks.PART.get())) {
|
||||
lvl.removeBlock(partPos, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,29 +3,18 @@
|
||||
"animations": {
|
||||
"idle": {
|
||||
"loop": true,
|
||||
"animation_length": 2,
|
||||
"animation_length": 0.25,
|
||||
"bones": {
|
||||
"bone2": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"vector": [0, 0, 0]
|
||||
},
|
||||
"1.0": {
|
||||
"vector": [0, 180, 0]
|
||||
"0.125": {
|
||||
"vector": [180, 0, 0]
|
||||
},
|
||||
"2.0": {
|
||||
"vector": [0, 360, 0]
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"0.0": {
|
||||
"vector": [0, 0, 0]
|
||||
},
|
||||
"1.0": {
|
||||
"vector": [0, 2, 0]
|
||||
},
|
||||
"2.0": {
|
||||
"vector": [0, 0, 0]
|
||||
"0.25": {
|
||||
"vector": [360, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,26 @@
|
||||
{
|
||||
"description": {
|
||||
"identifier": "geometry.unknown",
|
||||
"texture_width": 64,
|
||||
"texture_height": 64,
|
||||
"visible_bounds_width": 2,
|
||||
"visible_bounds_height": 2.5,
|
||||
"visible_bounds_offset": [0, 0.75, 0]
|
||||
"texture_width": 128,
|
||||
"texture_height": 128,
|
||||
"visible_bounds_width": 4,
|
||||
"visible_bounds_height": 3.5,
|
||||
"visible_bounds_offset": [0, 1.25, 0]
|
||||
},
|
||||
"bones": [
|
||||
{
|
||||
"name": "bone",
|
||||
"pivot": [0, 1, 0],
|
||||
"pivot": [17, 18, 0],
|
||||
"cubes": [
|
||||
{"origin": [-7, 1, -7], "size": [14, 5, 14], "inflate": 1, "uv": [0, 0]}
|
||||
{"origin": [-7, 1, -7], "size": [30, 12, 14], "inflate": 1, "uv": [0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bone2",
|
||||
"parent": "bone",
|
||||
"pivot": [0, 14, 0],
|
||||
"pivot": [17, 18, 0],
|
||||
"cubes": [
|
||||
{"origin": [-1, 9, -1], "size": [2, 11, 2], "uv": [0, 19]}
|
||||
{"origin": [-8, 7, -1], "size": [2, 11, 2], "pivot": [-7, 18, 0], "rotation": [-90, -90, 0], "uv": [0, 26]}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
{
|
||||
"credit": "Made with Blockbench",
|
||||
"parent": "builtin/entity",
|
||||
"texture_size": [
|
||||
64,
|
||||
64
|
||||
128,
|
||||
128
|
||||
],
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
@@ -15,9 +14,9 @@
|
||||
},
|
||||
"gui": {
|
||||
"rotation": [
|
||||
10.81,
|
||||
-60.3,
|
||||
-1.32
|
||||
10.809999999999945,
|
||||
-60.30000000000018,
|
||||
-1.3200000000001637
|
||||
],
|
||||
"translation": [
|
||||
-0.25,
|
||||
@@ -32,6 +31,6 @@
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"particle": "ibg:block/animated_block"
|
||||
"particle": "ibg:item/animated_block"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 395 B After Width: | Height: | Size: 499 B |
Reference in New Issue
Block a user