Skip to content

Commit 037d7d1

Browse files
committed
Black hole gaming
1 parent a03f6f9 commit 037d7d1

12 files changed

+421
-714
lines changed

src/main/java/de/dafuqs/spectrum/blocks/chests/BlackHoleChestBlock.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,11 @@ public <T extends BlockEntity> GameEventListener getGameEventListener(ServerWorl
5050

5151
@Override
5252
public BlockRenderType getRenderType(BlockState state) {
53-
return BlockRenderType.MODEL;
53+
return BlockRenderType.ENTITYBLOCK_ANIMATED;
5454
}
5555

5656
@Override
5757
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
5858
return SHAPE;
5959
}
60-
6160
}

src/main/java/de/dafuqs/spectrum/blocks/chests/BlackHoleChestBlockEntity.java

+108-4
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,108 @@ public class BlackHoleChestBlockEntity extends SpectrumChestBlockEntity implemen
4242
private static final int RANGE = 12;
4343
private final ItemAndExperienceEventQueue itemAndExperienceEventQueue;
4444
private final List<Item> filterItems;
45+
private State state;
46+
private boolean isOpen, isFull;
47+
float storageTarget, storagePos, lastStorageTarget, capTarget, capPos, lastCapTarget, orbTarget, orbPos, lastOrbTarget, yawTarget, orbYaw, lastYawTarget;
48+
long interpTicks, interpLength = 1, age;
49+
4550

4651
public BlackHoleChestBlockEntity(BlockPos blockPos, BlockState blockState) {
4752
super(SpectrumBlockEntities.BLACK_HOLE_CHEST, blockPos, blockState);
4853
this.itemAndExperienceEventQueue = new ItemAndExperienceEventQueue(new BlockPositionSource(this.pos), RANGE, this);
4954
this.filterItems = DefaultedList.ofSize(ITEM_FILTER_SLOT_COUNT, Items.AIR);
5055
}
5156

52-
public static void tick(@NotNull World world, BlockPos pos, BlockState state, BlackHoleChestBlockEntity blockEntity) {
57+
public static void tick(@NotNull World world, BlockPos pos, BlockState state, BlackHoleChestBlockEntity chest) {
58+
chest.updateFullState();
59+
chest.age++;
60+
61+
if (chest.isOpen) {
62+
if (chest.canFunction()) {
63+
chest.changeState(State.OPEN_ACTIVE);
64+
chest.interpLength = 7;
65+
}
66+
else {
67+
chest.changeState(State.OPEN_INACTIVE);
68+
chest.interpLength = 5;
69+
}
70+
}
71+
else {
72+
if (chest.isFull) {
73+
chest.changeState(State.FULL);
74+
chest.interpLength = 12;
75+
}
76+
else if (chest.canFunction()) {
77+
chest.changeState(State.CLOSED_ACTIVE);
78+
chest.interpLength = 15;
79+
}
80+
else {
81+
chest.changeState(State.CLOSED_INACTIVE);
82+
chest.interpLength = 10;
83+
}
84+
}
85+
86+
if (chest.interpTicks < chest.interpLength) {
87+
chest.interpTicks++;
88+
}
89+
5390
if (world.isClient) {
54-
blockEntity.lidAnimator.step();
91+
chest.lidAnimator.step();
5592
} else {
56-
blockEntity.itemAndExperienceEventQueue.tick(world);
93+
chest.itemAndExperienceEventQueue.tick(world);
5794
if (world.getTime() % 80 == 0 && !SpectrumChestBlock.isChestBlocked(world, pos)) {
58-
searchForNearbyEntities(blockEntity);
95+
searchForNearbyEntities(chest);
96+
}
97+
}
98+
}
99+
100+
public long getRenderTime() {
101+
return age % 50000;
102+
}
103+
104+
public void changeState(State state) {
105+
if (this.state != state) {
106+
this.state = state;
107+
lastCapTarget = capPos;
108+
lastOrbTarget = orbPos;
109+
lastStorageTarget = storagePos;
110+
lastYawTarget = orbYaw;
111+
interpTicks = 0;
112+
}
113+
}
114+
115+
public void updateFullState() {
116+
if (!world.isClient()) {
117+
isFull = isFull();
118+
SpectrumS2CPacketSender.sendBlackHoleChestUpdate(this);
119+
}
120+
}
121+
122+
public State getState() {
123+
return state;
124+
}
125+
126+
public boolean canFunction() {
127+
return !SpectrumChestBlock.isChestBlocked(world, this.pos) && !isFull;
128+
}
129+
130+
public boolean isFull() {
131+
for (int i = 0; i < inventory.size() - 1; i++) {
132+
var stack = inventory.get(i);
133+
if (stack.getCount() < stack.getMaxCount()) {
134+
return false;
59135
}
60136
}
137+
138+
return true;
139+
}
140+
141+
public boolean isFullButActually() {
142+
return isFull;
143+
}
144+
145+
public void setFull(boolean full) {
146+
isFull = full;
61147
}
62148

63149
private static void searchForNearbyEntities(@NotNull BlackHoleChestBlockEntity blockEntity) {
@@ -80,6 +166,14 @@ private static void searchForNearbyEntities(@NotNull BlackHoleChestBlockEntity b
80166
protected static @NotNull Box getBoxWithRadius(BlockPos blockPos, int radius) {
81167
return Box.of(Vec3d.ofCenter(blockPos), radius, radius, radius);
82168
}
169+
170+
@Override
171+
public boolean onSyncedBlockEvent(int type, int data) {
172+
if (type == 1) {
173+
isOpen = data > 0;
174+
}
175+
return super.onSyncedBlockEvent(type, data);
176+
}
83177

84178
@Override
85179
protected Text getContainerName() {
@@ -97,6 +191,7 @@ public void writeNbt(NbtCompound tag) {
97191
for (int i = 0; i < ITEM_FILTER_SLOT_COUNT; i++) {
98192
tag.putString("Filter" + i, Registries.ITEM.getId(this.filterItems.get(i)).toString());
99193
}
194+
tag.putLong("age", age);
100195
}
101196

102197
@Override
@@ -107,6 +202,7 @@ public void readNbt(NbtCompound tag) {
107202
this.filterItems.set(i, Registries.ITEM.get(new Identifier(tag.getString("Filter" + i))));
108203
}
109204
}
205+
age = tag.getLong("age");
110206
}
111207

112208
@Override
@@ -239,4 +335,12 @@ public boolean canInsert(int slot, ItemStack stack, @Nullable Direction dir) {
239335
public boolean canExtract(int slot, ItemStack stack, Direction dir) {
240336
return true;
241337
}
338+
339+
public enum State {
340+
OPEN_INACTIVE,
341+
OPEN_ACTIVE,
342+
CLOSED_ACTIVE,
343+
CLOSED_INACTIVE,
344+
FULL
345+
}
242346
}

src/main/java/de/dafuqs/spectrum/blocks/chests/BlackHoleChestBlockEntityRenderer.java

+84-15
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,118 @@
11
package de.dafuqs.spectrum.blocks.chests;
22

33
import de.dafuqs.spectrum.*;
4+
import de.dafuqs.spectrum.registries.SpectrumBlocks;
45
import net.fabricmc.api.*;
6+
import net.minecraft.block.BlockState;
7+
import net.minecraft.block.ChestBlock;
58
import net.minecraft.client.model.*;
69
import net.minecraft.client.render.*;
710
import net.minecraft.client.render.block.entity.*;
811
import net.minecraft.client.util.*;
912
import net.minecraft.client.util.math.*;
1013
import net.minecraft.screen.*;
14+
import net.minecraft.util.math.Direction;
15+
import net.minecraft.util.math.MathHelper;
16+
import net.minecraft.util.math.RotationAxis;
1117
import org.jetbrains.annotations.*;
1218

1319
@Environment(EnvType.CLIENT)
1420
public class BlackHoleChestBlockEntityRenderer implements BlockEntityRenderer<BlackHoleChestBlockEntity> {
1521

16-
private static final SpriteIdentifier spriteIdentifier = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, SpectrumCommon.locate("block/black_block"));
22+
private static final SpriteIdentifier spriteIdentifier = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, SpectrumCommon.locate("block/black_hole_chest"));
1723
private final ModelPart root;
24+
private final ModelPart shell;
25+
private final ModelPart cap;
26+
private final ModelPart storage;
27+
private final ModelPart orb;
1828

1929
public BlackHoleChestBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) {
2030
TexturedModelData texturedModelData = getTexturedModelData();
21-
root = texturedModelData.createModel();
31+
this.root = texturedModelData.createModel();
32+
this.shell = root.getChild("shell");
33+
this.cap = root.getChild("cap");
34+
this.storage = root.getChild("storage");
35+
this.orb = root.getChild("orb");
2236
}
2337

2438
public static @NotNull TexturedModelData getTexturedModelData() {
2539
ModelData modelData = new ModelData();
2640
ModelPartData modelPartData = modelData.getRoot();
27-
modelPartData.addChild("lid", ModelPartBuilder.create().uv(1, 1).cuboid(5.0F, 7.0F, 5.0F, 6.0F, 3.0F, 6.0F), ModelTransform.pivot(0.0F, 0.0F, 0.0F));
28-
modelPartData.addChild("lid2", ModelPartBuilder.create().uv(1, 1).cuboid(7.0F, 4.0F, 7.0F, 2.0F, 3.0F, 2.0F), ModelTransform.pivot(0.0F, 0.0F, 0.0F));
29-
return TexturedModelData.of(modelData, 32, 32);
41+
ModelPartData shell = modelPartData.addChild("shell", ModelPartBuilder.create().uv(0, 0).cuboid(-7.0F, -9.0F, -7.0F, 14.0F, 9.0F, 14.0F, new Dilation(0.0F))
42+
.uv(0, 39).cuboid(-5.0F, -9.0F, -5.0F, 10.0F, 9.0F, 10.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 24.0F, 0.0F));
43+
44+
ModelPartData cap = modelPartData.addChild("cap", ModelPartBuilder.create().uv(40, 39).cuboid(-5.0F, -6.0F, -5.0F, 10.0F, 4.0F, 10.0F, new Dilation(0.0F))
45+
.uv(82, 2).cuboid(-4.0F, -5.0F, -4.0F, 8.0F, 3.0F, 8.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 24.0F, 0.0F));
46+
47+
ModelPartData storage = modelPartData.addChild("storage", ModelPartBuilder.create().uv(42, 0).cuboid(-5.0F, -2.0F, -5.0F, 10.0F, 2.0F, 10.0F, new Dilation(0.0F))
48+
.uv(56, 13).cuboid(-4.0F, -2.0F, -4.0F, 8.0F, 2.0F, 8.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 24.0F, 0.0F));
49+
50+
ModelPartData orb = modelPartData.addChild("orb", ModelPartBuilder.create().uv(0, 0).cuboid(-1.0F, -1.0F, -1.0F, 2.0F, 2.0F, 2.0F, new Dilation(0.0F))
51+
.uv(30, 39).cuboid(-2.5F, -2.5F, -2.5F, 5.0F, 5.0F, 5.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 15.4F, 0.0F));
52+
return TexturedModelData.of(modelData, 128, 128);
3053
}
3154

3255
@Override
33-
public void render(BlackHoleChestBlockEntity entity, float tickDelta, MatrixStack matrixStack, VertexConsumerProvider vertexConsumers, int light, int overlay) {
56+
public void render(BlackHoleChestBlockEntity chest, float tickDelta, MatrixStack matrixStack, VertexConsumerProvider vertexConsumers, int light, int overlay) {
3457
matrixStack.push();
35-
matrixStack.translate(0.5D, 0.5D, 0.5D);
36-
matrixStack.translate(-0.5D, -0.5D, -0.5D);
3758

38-
float openFactor = entity.getAnimationProgress(tickDelta);
39-
openFactor = 1.0F - openFactor;
40-
openFactor = 1.0F - openFactor * openFactor * openFactor;
59+
boolean bl = chest.getWorld() != null;
60+
BlockState blockState = bl ? chest.getCachedState() : SpectrumBlocks.BLACK_HOLE_CHEST.getDefaultState().with(ChestBlock.FACING, Direction.SOUTH);
61+
float f = (blockState.get(ChestBlock.FACING)).asRotation();
62+
matrixStack.translate(0.5D, 1.5D, 0.5D);
63+
matrixStack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-f));
64+
matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180));
65+
var time = chest.getRenderTime();
66+
67+
final double orbTransform = Math.sin((time + tickDelta) / 9F);
68+
final float potentialYaw = (time + tickDelta) / 6F;
69+
switch (chest.getState()) {
70+
case OPEN_ACTIVE -> {
71+
chest.storageTarget = 9;
72+
chest.capTarget = 12;
73+
chest.orbTarget = (float) (15 + orbTransform);
74+
chest.yawTarget = potentialYaw;
75+
}
76+
case OPEN_INACTIVE -> {
77+
chest.storageTarget = 9;
78+
chest.capTarget = 12;
79+
chest.orbTarget = chest.capTarget;
80+
}
81+
case CLOSED_ACTIVE -> {
82+
chest.capTarget = 0;
83+
chest.storageTarget = 0;
84+
chest.orbTarget = (float) (12.5 + orbTransform * 2.5F);
85+
chest.yawTarget = potentialYaw;
86+
87+
}
88+
case CLOSED_INACTIVE -> {
89+
chest.capTarget = 0;
90+
chest.storageTarget = chest.capTarget;
91+
chest.orbTarget = chest.capTarget;
92+
}
93+
case FULL -> {
94+
chest.capTarget = 9;
95+
chest.storageTarget = chest.capTarget;
96+
chest.orbTarget = chest.capTarget;
97+
}
98+
}
4199

42-
root.pivotY = openFactor * 5;
43-
44-
VertexConsumer vertexConsumer = spriteIdentifier.getVertexConsumer(vertexConsumers, RenderLayer::getEntityCutout);
100+
var interp = MathHelper.clamp((chest.interpTicks + tickDelta) / chest.interpLength, 0F, 1F);
101+
chest.capPos = MathHelper.lerp(interp, chest.lastCapTarget, chest.capTarget);
102+
chest.storagePos = MathHelper.lerp(interp, chest.lastStorageTarget, chest.storageTarget);
103+
chest.orbPos = MathHelper.lerp(interp, chest.lastOrbTarget, chest.orbTarget);
104+
chest.orbYaw = MathHelper.lerp(interp, chest.lastYawTarget, chest.yawTarget);
105+
106+
cap.pivotY = 24 - chest.capPos;
107+
storage.pivotY = 24 - chest.storagePos;
108+
orb.pivotY = 15.4F - chest.orbPos;
109+
orb.yaw = chest.yawTarget;
110+
111+
112+
storage.hidden = storage.pivotY > 23.99F;
113+
VertexConsumer vertexConsumer = spriteIdentifier.getVertexConsumer(vertexConsumers, RenderLayer::getEntityTranslucent);
45114
root.render(matrixStack, vertexConsumer, light, overlay);
46-
115+
47116
matrixStack.pop();
48117
}
49118

0 commit comments

Comments
 (0)