Skip to content

Commit

Permalink
fix: improvements to the Cryogenic Chamber (#380)
Browse files Browse the repository at this point in the history
* fix: adjusted player's position in Cryogenic Chambers and fixed typo Cyro

* refactor: combined Cryogenic Chamber into a single model

* fix: adjusted display values of Cryogenic Chamber item model

* refactor: made the style of JSON files more consistent

* fix: made the Cryogenic Chamber cooldown message translatable

* fix: made bounding box shapes static final

* fix: changed messages to be more appropriate to Cryogenic Chambers

* refactor: made usage of BedSleepingProblem consistent with GCEventHandlers

* feat: added occupied block state to Cryogenic Chamber

* fix: resolves #353

* fix: wrote mixin to draw better block outlines for translucent blocks such as the Cryogenic Chamber and Player Transport Tube

* feat: added getShape method for Player Transport Tube to give a tube shape rather than just a box

* fix: always allow players in creative to use Cryogenic Chambers

* fix: corrected Cryogenic Chamber cooldown to display the number of seconds rather than ticks
  • Loading branch information
Roelymole authored Jan 4, 2025
1 parent 83f7c93 commit 2228bc6
Show file tree
Hide file tree
Showing 17 changed files with 243 additions and 166 deletions.
4 changes: 4 additions & 0 deletions src/main/generated/assets/galacticraft/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@
"category.recipe_viewer.circuit_fabricator": "Circuit Fabricating",
"category.recipe_viewer.compressing": "Compressing",
"chat.galacticraft.bed_fail": "Uh oh, what if the oxygen runs out when I am asleep? I'll need a Cryogenic Chamber to sleep in space!",
"chat.galacticraft.chamber_hot": "The chamber is way too hot right now! It needs %s seconds to cool down before I sleep again.",
"chat.galacticraft.chamber_obstructed": "This cryogenic chamber is obstructed",
"chat.galacticraft.chamber_occupied": "This cryogenic chamber is occupied",
"chat.galacticraft.chamber_too_far_away": "You may not rest now; the cryogenic chamber is too far away",
"chat.galacticraft.rocket.warning": "Press again to launch.",
"commands.galacticraft.debug.registry.dump": "Dumped: %s",
"commands.galacticraft.debug.registry.id": "%s - %s: %s",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@

public interface CryogenicAccessor {

default void beginCyroSleep() {
default void beginCryoSleep() {
throw new RuntimeException("This should be overridden by mixin!");
}

default void endCyroSleep() {
default void endCryoSleep() {
throw new RuntimeException("This should be overridden by mixin!");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
import dev.galacticraft.mod.content.GCBlocks;
import dev.galacticraft.mod.content.block.entity.CryogenicChamberBlockEntity;
import dev.galacticraft.mod.particle.GCParticleTypes;
import dev.galacticraft.mod.util.Translations;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.TickRateManager;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
Expand All @@ -45,6 +47,7 @@
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.phys.BlockHitResult;
Expand All @@ -60,10 +63,13 @@ public class CryogenicChamberBlock extends BaseEntityBlock implements MultiBlock
public static final MapCodec<CryogenicChamberBlock> CODEC = simpleCodec(CryogenicChamberBlock::new);
private static final List<BlockPos> PARTS = List.of(new BlockPos(0, 1, 0), new BlockPos(0, 2, 0));
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final BooleanProperty OCCUPIED = BlockStateProperties.OCCUPIED;
private static final VoxelShape SHAPE = Shapes.box(0, 0, 0, 1, 3, 1);
public static final TickRateManager TICKS = new TickRateManager();

public CryogenicChamberBlock(Properties properties) {
super(properties);
this.registerDefaultState(this.getStateDefinition().any().setValue(FACING, Direction.NORTH));
this.registerDefaultState(this.getStateDefinition().any().setValue(FACING, Direction.NORTH).setValue(OCCUPIED, false));
}

@Override
Expand All @@ -82,9 +88,14 @@ public RenderShape getRenderShape(BlockState blockState) {
return RenderShape.MODEL;
}

@Override
public VoxelShape getShape(BlockState state, BlockGetter blockGetter, BlockPos pos, CollisionContext context) {
return SHAPE;
}

@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING);
builder.add(FACING, OCCUPIED);
}

@Override
Expand Down Expand Up @@ -127,12 +138,11 @@ public void setPlacedBy(Level level, BlockPos blockPos, BlockState blockState, @

@Override
public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) {
BlockState state = super.playerWillDestroy(level, blockPos, blockState, player);
for (var otherPart : this.getOtherParts(blockState)) {
otherPart = otherPart.immutable().offset(blockPos);
level.destroyBlock(otherPart, false);
}
return state;
return super.playerWillDestroy(level, blockPos, blockState, player);
}

@Override
Expand All @@ -148,15 +158,15 @@ public void onPartDestroyed(Level level, Player player, BlockState blockState, B
}

@Override
public void wasExploded(Level world, BlockPos pos, Explosion explosion) {
for (BlockPos part : this.getOtherParts(world.getBlockState(pos))) {
part = pos.immutable().offset(part);
if (!(world.getBlockEntity(part) instanceof MultiBlockPart)) {
public void wasExploded(Level level, BlockPos blockPos, Explosion explosion) {
for (BlockPos otherPart : this.getOtherParts(level.getBlockState(blockPos))) {
otherPart = otherPart.immutable().offset(blockPos);
if (!(level.getBlockEntity(otherPart) instanceof MultiBlockPart)) {
continue;
}
world.removeBlock(part, false);
level.destroyBlock(otherPart, false);
}
super.wasExploded(world, pos, explosion);
super.wasExploded(level, blockPos, explosion);
}

@Override
Expand Down Expand Up @@ -184,16 +194,29 @@ protected InteractionResult useWithoutItem(BlockState state, Level level, BlockP
public InteractionResult multiBlockUseWithoutItem(BlockState baseState, Level level, BlockPos basePos, Player player) {
if (level.isClientSide()) return InteractionResult.CONSUME;

if(player.getCryogenicChamberCooldown() == 0) {
player.beginCyroSleep();
if (baseState.getValue(OCCUPIED).booleanValue()) {
player.displayClientMessage(Component.translatable(Translations.Chat.CHAMBER_OCCUPIED), true);
} else if (player.isCreative() || player.getCryogenicChamberCooldown() == 0) {
player.beginCryoSleep();
level.setBlockAndUpdate(basePos, baseState.setValue(OCCUPIED, true));

player.startSleepInBed(basePos).ifLeft(problem -> {
if (problem.getMessage() != null) player.displayClientMessage(problem.getMessage(), true);

player.endCyroSleep();
switch(problem) {
case Player.BedSleepingProblem.OBSTRUCTED:
player.displayClientMessage(Component.translatable(Translations.Chat.CHAMBER_OBSTRUCTED), true);
break;
case Player.BedSleepingProblem.TOO_FAR_AWAY:
player.displayClientMessage(Component.translatable(Translations.Chat.CHAMBER_TOO_FAR_AWAY), true);
break;
default:
player.displayClientMessage(problem.getMessage(), true);
}

player.endCryoSleep();
level.setBlockAndUpdate(basePos, baseState.setValue(OCCUPIED, false));
});
} else {
player.displayClientMessage(Component.literal("The chamber is way to hot right now! It needs " + player.getCryogenicChamberCooldown() + " seconds to cool down before I sleep again."), false);
player.displayClientMessage(Component.translatable(Translations.Chat.CHAMBER_HOT, (int)(player.getCryogenicChamberCooldown() / TICKS.tickrate())), false);
}

return InteractionResult.SUCCESS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
public class CryogenicChamberPart extends BaseEntityBlock {
public static final MapCodec<CryogenicChamberPart> CODEC = simpleCodec(CryogenicChamberPart::new);
public static final BooleanProperty TOP = BooleanProperty.create("top");
private static final VoxelShape SHAPE_TOP = Shapes.box(0, -2, 0, 1, 1, 1);
private static final VoxelShape SHAPE_MID = Shapes.box(0, -1, 0, 1, 2, 1);

public CryogenicChamberPart(Properties properties) {
super(properties);
Expand Down Expand Up @@ -84,6 +86,11 @@ public RenderShape getRenderShape(BlockState blockState) {
return RenderShape.MODEL;
}

@Override
public VoxelShape getShape(BlockState state, BlockGetter blockGetter, BlockPos pos, CollisionContext context) {
return state.getValue(TOP) ? SHAPE_TOP : SHAPE_MID;
}

@Override
public BlockState playerWillDestroy(Level level, BlockPos blockPos, BlockState blockState, Player player) {
var partBE = level.getBlockEntity(blockPos);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,28 @@

package dev.galacticraft.mod.content.block.special;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;

public class TransportTube extends Block {
private static final VoxelShape NORTH = Block.box(0, 0, 14, 16, 16, 16);
private static final VoxelShape SOUTH = Block.box(0, 0, 0, 16, 16, 2);
private static final VoxelShape EAST = Block.box(14, 0, 0, 16, 16, 16);
private static final VoxelShape WEST = Block.box(0, 0, 0, 2, 16, 16);
private static final VoxelShape SHAPE = Shapes.or(NORTH, SOUTH, EAST, WEST);

public TransportTube(Properties properties) {
super(properties);
}

@Override
public VoxelShape getShape(BlockState state, BlockGetter blockGetter, BlockPos pos, CollisionContext context) {
return SHAPE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,10 @@ protected void generateBiomeTranslations() {

protected void generateChatTranslations() {
this.add(Chat.BED_FAIL, "Uh oh, what if the oxygen runs out when I am asleep? I'll need a Cryogenic Chamber to sleep in space!");
this.add(Chat.CHAMBER_HOT, "The chamber is way too hot right now! It needs %s seconds to cool down before I sleep again.");
this.add(Chat.CHAMBER_OBSTRUCTED, "This cryogenic chamber is obstructed");
this.add(Chat.CHAMBER_OCCUPIED, "This cryogenic chamber is occupied");
this.add(Chat.CHAMBER_TOO_FAR_AWAY, "You may not rest now; the cryogenic chamber is too far away");
this.add(Chat.ROCKET_WARNING, "Press again to launch.");

this.add(Subtitles.THROW_METEOR_CHUNK, "Meteor Chunk flies");
Expand Down
19 changes: 14 additions & 5 deletions src/main/java/dev/galacticraft/mod/events/GCEventHandlers.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BedBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import org.jetbrains.annotations.Nullable;

public class GCEventHandlers {
Expand All @@ -61,9 +62,12 @@ public static void init() {
}

public static InteractionResult allowCryogenicSleep(LivingEntity entity, BlockPos sleepingPos, BlockState state, boolean vanillaResult) {
return entity.isInCryoSleep()
? InteractionResult.SUCCESS
: InteractionResult.PASS;
if (state.getBlock() instanceof CryogenicChamberBlock) {
return entity.isInCryoSleep()
? InteractionResult.SUCCESS
: InteractionResult.PASS;
}
return InteractionResult.PASS;
}

public static Direction changeSleepPosition(LivingEntity entity, BlockPos sleepingPos, @Nullable Direction sleepingDirection) {
Expand Down Expand Up @@ -94,8 +98,13 @@ public static InteractionResult canCryoSleep(Player player, BlockPos sleepingPos
}

public static void onWakeFromCryoSleep(LivingEntity entity, BlockPos sleepingPos) {
if (!entity.level().isClientSide() && entity.isInCryoSleep()) {
entity.endCyroSleep();
Level level = entity.level();
if (!level.isClientSide() && entity.isInCryoSleep()) {
entity.endCryoSleep();
BlockState baseState = level.getBlockState(sleepingPos);
if (baseState.getBlock() instanceof CryogenicChamberBlock) {
level.setBlockAndUpdate(sleepingPos, baseState.setValue(BlockStateProperties.OCCUPIED, false));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
Expand All @@ -57,12 +58,12 @@ public LivingEntityMixin(EntityType<?> entityType, Level level) {
}

@Override
public void beginCyroSleep() {
public void beginCryoSleep() {
this.entityData.set(IS_IN_CRYO_SLEEP_ID, true);
}

@Override
public void endCyroSleep() {
public void endCryoSleep() {
this.entityData.set(IS_IN_CRYO_SLEEP_ID, false);
}

Expand Down Expand Up @@ -106,7 +107,8 @@ public void setCryogenicChamberCooldown(int cryogenicChamberCooldown) {
@Inject(method = "setPosToBed", at = @At("HEAD"), cancellable = true)
private void gc$setCryoSleepPos(BlockPos blockPos, CallbackInfo ci) {
if (isInCryoSleep()) {
this.setPos(blockPos.getX(), blockPos.getY() + 1F, blockPos.getZ());
Vec3 pos = blockPos.getBottomCenter();
this.setPos(pos.x, pos.y + 1F, pos.z);
ci.cancel();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@

import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import dev.galacticraft.mod.Constant;
import dev.galacticraft.mod.client.render.dimension.OverworldRenderer;
import dev.galacticraft.mod.content.block.special.CryogenicChamberBlock;
import dev.galacticraft.mod.content.block.special.CryogenicChamberPart;
import dev.galacticraft.mod.content.block.special.TransportTube;
import dev.galacticraft.mod.content.entity.orbital.RocketEntity;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
Expand All @@ -34,7 +38,13 @@
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
Expand All @@ -44,13 +54,40 @@

@Mixin(LevelRenderer.class)
public class LevelRendererMixin {
// Define the RGBA values of the block outline for translucent blocks
private static float R = 0.15f;
private static float G = 0.15f;
private static float B = 0.15f;
private static float A = 1.0f; // opaque

@Unique
private OverworldRenderer worldRenderer;

@Inject(method = "<init>", at = @At("TAIL"))
private void gc$setupRenderer(Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers, CallbackInfo ci) {
this.worldRenderer = new OverworldRenderer();
}

@Inject(method = "renderHitOutline", at = @At("HEAD"), cancellable = true)
private void onRenderHitOutline(PoseStack poseStack, VertexConsumer vertexConsumer, Entity entity, double cameraX, double cameraY, double cameraZ, BlockPos blockPos, BlockState blockState, CallbackInfo ci) {
if (blockState.getBlock() instanceof CryogenicChamberBlock || blockState.getBlock() instanceof CryogenicChamberPart || blockState.getBlock() instanceof TransportTube) {
// LevelRenderer.renderShape(poseStack, vertexConsumer, blockState.getShape(entity.level(), blockPos, CollisionContext.of(entity)), (double)blockPos.getX() - cameraX, (double)blockPos.getY() - cameraY, (double)blockPos.getZ() - cameraZ, 0.0f, 0.0f, 0.0f, 0.0f);
VoxelShape voxelShape = blockState.getShape(entity.level(), blockPos, CollisionContext.of(entity));
double d = (double)blockPos.getX() - cameraX;
double d2 = (double)blockPos.getY() - cameraY;
double d3 = (double)blockPos.getZ() - cameraZ;
PoseStack.Pose pose = poseStack.last();
voxelShape.forAllEdges((d4, d5, d6, d7, d8, d9) -> {
float f5 = (float)(d7 - d4);
float f6 = (float)(d8 - d5);
float f7 = (float)(d9 - d6);
float f8 = Mth.sqrt(f5 * f5 + f6 * f6 + f7 * f7);
vertexConsumer.addVertex(pose, (float)(d4 + d), (float)(d5 + d2), (float)(d6 + d3)).setColor(R, G, B, A).setNormal(pose, f5 /= f8, f6 /= f8, f7 /= f8);
vertexConsumer.addVertex(pose, (float)(d7 + d), (float)(d8 + d2), (float)(d9 + d3)).setColor(R, G, B, A).setNormal(pose, f5, f6, f7);
});
ci.cancel();
}
}

@Inject(method = "renderSky", at = @At("HEAD"), cancellable = true)
public void gc$renderSky(Matrix4f matrix4f, Matrix4f projectionMatrix, float tickDelta, Camera camera, boolean thickFog, Runnable fogCallback, CallbackInfo ci) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/dev/galacticraft/mod/util/Translations.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ interface BannerPattern {

interface Chat {
String BED_FAIL = "chat.galacticraft.bed_fail";
String CHAMBER_HOT = "chat.galacticraft.chamber_hot";
String CHAMBER_OBSTRUCTED = "chat.galacticraft.chamber_obstructed";
String CHAMBER_OCCUPIED = "chat.galacticraft.chamber_occupied";
String CHAMBER_TOO_FAR_AWAY = "chat.galacticraft.chamber_too_far_away";
String ROCKET_WARNING = "chat.galacticraft.rocket.warning";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"variants": {
"facing=north": { "model": "galacticraft:block/cryogenic_chamber_bottom"},
"facing=east": { "model": "galacticraft:block/cryogenic_chamber_bottom", "y": 90 },
"facing=west": { "model": "galacticraft:block/cryogenic_chamber_bottom", "y": 270 },
"facing=south": { "model": "galacticraft:block/cryogenic_chamber_bottom", "y": 180 }
"": {
"model": "galacticraft:block/invisible_machine"
}
}
}
Loading

0 comments on commit 2228bc6

Please sign in to comment.