mirror of
https://github.com/XevianLight/Aphelion.git
synced 2026-05-11 10:00:54 +01:00
Compare commits
6 Commits
903c7f7d17
...
gravity-sy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3154d32d79 | ||
|
|
aaa55b087f | ||
|
|
d9bd26e8a0 | ||
|
|
010fc7307f | ||
|
|
9356c43ea7 | ||
|
|
fa41966de4 |
@@ -1,11 +1,12 @@
|
||||
// 1.21.1 2026-01-28T08:47:15.3186366 Loot Tables
|
||||
// 1.21.1 2026-01-26T19:04:46.4976369 Loot Tables
|
||||
// 1.21.1 2026-02-06T10:36:07.5023829 Loot Tables
|
||||
69d8318ddba171526d1fabb87d9d93548ed8598e data/aphelion/loot_table/blocks/arc_furnace_casing.json
|
||||
05f08985e601d30116f67e2f07b48b03b40cdca6 data/aphelion/loot_table/blocks/block_steel.json
|
||||
ff43a9c3741faf10b1e156a7a74d5cfb035cc118 data/aphelion/loot_table/blocks/dimension_changer.json
|
||||
b63130d9c10485676303d729807b6fcaac080294 data/aphelion/loot_table/blocks/electric_arc_furnace.json
|
||||
afb6519a03415b8e0d5bafc9fadb70905a398046 data/aphelion/loot_table/blocks/oxygen_test_block.json
|
||||
086c97543700ccc2f815da4e6c29f11159766889 data/aphelion/loot_table/blocks/gravity_test_block.json
|
||||
b9cfe672ead8e2673a7b2f5c4cec831e7e8e7040 data/aphelion/loot_table/blocks/launch_pad.json
|
||||
afb6519a03415b8e0d5bafc9fadb70905a398046 data/aphelion/loot_table/blocks/oxygen_test_block.json
|
||||
2c6748b2cfb5b78e0cc95a2f3583d4e50cb4c964 data/aphelion/loot_table/blocks/rocket_assemblerblock.json
|
||||
1ab50c99e9f478840b9d003fd56ebdcab12fbbce data/aphelion/loot_table/blocks/test_block.json
|
||||
7d8eeb99a1bc942a6e2cf292b21fd4534062b5ab data/aphelion/loot_table/blocks/vacuum_arc_furnace_controller.json
|
||||
797bf9839d79e08b4832c9eaf3cb303b0471ed0c data/aphelion/loot_table/blocks/vaf_dummy_block.json
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
// 1.21.1 2026-01-28T08:47:15.3176368 Block States: aphelion
|
||||
// 1.21.1 2026-01-26T20:40:43.8251623 Block States: aphelion
|
||||
// 1.21.1 2026-02-06T10:36:07.5013847 Block States: aphelion
|
||||
851ff42f7b21dec86107c8e0cefb3934ae4ebc08 assets/aphelion/blockstates/block_steel.json
|
||||
30b9c0efd7aaadb5412d98e4568f98b3632adbb9 assets/aphelion/blockstates/dimension_changer.json
|
||||
cb4287104006c80c8396b290ab5258df65d62cef assets/aphelion/blockstates/electric_arc_furnace.json
|
||||
1975ab6c73f76642f8b6cfed00e0739b4ea5775f assets/aphelion/blockstates/gravity_test_block.json
|
||||
28131a570d3666b7f323de4ad8a69e52ceec92e2 assets/aphelion/blockstates/oxygen_test_block.json
|
||||
b86c50fddcf6c8c6c19cb748529239d5962a3ede assets/aphelion/blockstates/test_block.json
|
||||
a810b97f4dace35d026f28d96cb9c47c93600d75 assets/aphelion/models/block/block_steel.json
|
||||
2d3592b7ab7132908709243e97540151e0fb762e assets/aphelion/models/block/dimension_changer.json
|
||||
5f7e8674070f31a63875b5d6147153bfa0eef61a assets/aphelion/models/block/electric_arc_furnace.json
|
||||
ad49034f318c6bc14a4844cf598c6999296aa8a0 assets/aphelion/models/block/gravity_test_block.json
|
||||
746f23f150a01524ad03cbd1eb822bfbb7cf453b assets/aphelion/models/block/oxygen_test_block.json
|
||||
e0971228b4a1c4bc9dbab58a7dacdc3ae6037e02 assets/aphelion/models/block/test_block.json
|
||||
cdc831b0f1c462be64825fd34bd446e5b95afac6 assets/aphelion/models/item/arc_furnace_casing.json
|
||||
3599f9037eb2f66de1765318b97ab564c3eae92f assets/aphelion/models/item/block_steel.json
|
||||
db0ec473a016ce05c258cde18a217d47a9ea8324 assets/aphelion/models/item/dimension_changer.json
|
||||
279080c06ada87f54fd0a7b885b256dbe25a946a assets/aphelion/models/item/electric_arc_furnace.json
|
||||
8de1f7597e1fa82c5603a88040ad935aa1cb9b29 assets/aphelion/models/item/gravity_test_block.json
|
||||
24cf60e70f7d9450b0e70cf017662e80971bae17 assets/aphelion/models/item/oxygen_test_block.json
|
||||
74418ef1cf678e72e7534924274688ef5a68af0e assets/aphelion/models/item/test_block.json
|
||||
88ca3602517e99f7feaed57eddfc96965a25761c assets/aphelion/models/item/vacuum_arc_furnace_controller.json
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "aphelion:block/gravity_test_block"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "aphelion:block/gravity_test_block"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "aphelion:block/gravity_test_block"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "aphelion:gravity_test_block"
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "aphelion:blocks/gravity_test_block"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
],
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "minecraft:air"
|
||||
}
|
||||
],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "aphelion:blocks/rocket_assemblerblock"
|
||||
}
|
||||
@@ -24,10 +24,7 @@ import net.xevianlight.aphelion.fluid.BaseFluidType;
|
||||
import net.xevianlight.aphelion.fluid.ModFluidTypes;
|
||||
import net.xevianlight.aphelion.fluid.ModFluids;
|
||||
import net.xevianlight.aphelion.recipe.ModRecipes;
|
||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceScreen;
|
||||
import net.xevianlight.aphelion.screen.ModMenuTypes;
|
||||
import net.xevianlight.aphelion.screen.TestBlockScreen;
|
||||
import net.xevianlight.aphelion.screen.VacuumArcFurnaceScreen;
|
||||
import net.xevianlight.aphelion.screen.*;
|
||||
import org.slf4j.Logger;
|
||||
import net.xevianlight.aphelion.entites.vehicles.RocketRenderer;
|
||||
|
||||
@@ -147,6 +144,7 @@ public class Aphelion {
|
||||
event.register(ModMenuTypes.TEST_BLOCK_MENU.get(), TestBlockScreen::new);
|
||||
event.register(ModMenuTypes.ELECTRIC_ARC_FURNACE_MENU.get(), ElectricArcFurnaceScreen::new);
|
||||
event.register(ModMenuTypes.VACUUM_ARC_FURNACE_MENU.get(), VacuumArcFurnaceScreen::new);
|
||||
event.register(ModMenuTypes.GRAVITY_TEST_BLOCK_MENU.get(), GravityTestBlockScreen::new);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package net.xevianlight.aphelion.block.custom;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.xevianlight.aphelion.block.custom.base.BasicEntityBlock;
|
||||
import net.xevianlight.aphelion.block.entity.custom.GravityTestBlockEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.OxygenTestBlockEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class GravityTestBlock extends BasicEntityBlock {
|
||||
|
||||
public GravityTestBlock(Properties properties) {super(properties, true);}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {return null;}
|
||||
|
||||
@Override
|
||||
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new GravityTestBlockEntity(blockPos, blockState);
|
||||
}
|
||||
|
||||
public static Properties getProperties() {return Properties.of();}
|
||||
|
||||
@Override
|
||||
protected void onRemove(BlockState state, @NotNull Level level, @NotNull BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||
if (state.getBlock() != newState.getBlock()) {
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof GravityTestBlockEntity BE) {
|
||||
BE.removeGravityArea();
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, movedByPiston);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||
|
||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof GravityTestBlockEntity testBlockEntity) {
|
||||
serverPlayer.openMenu(new SimpleMenuProvider(testBlockEntity, Component.literal("Gravity Test Block")), pos);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(level.isClientSide);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package net.xevianlight.aphelion.block.entity.custom;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||
import net.xevianlight.aphelion.block.custom.base.TickableBlockEntity;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
||||
import net.xevianlight.aphelion.core.saveddata.GravitySavedData;
|
||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceMenu;
|
||||
import net.xevianlight.aphelion.screen.GravityTestBlockMenu;
|
||||
import net.xevianlight.aphelion.systems.GravityService;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class GravityTestBlockEntity extends BlockEntity implements TickableBlockEntity, MenuProvider {
|
||||
|
||||
public GravityTestBlockEntity(BlockPos pos, BlockState blockState) {super(ModBlockEntities.GRAVITY_TEST_BLOCK_ENTITY.get(), pos, blockState);}
|
||||
|
||||
public int areaSize = 5;
|
||||
public float gravityStrength = 5f;
|
||||
private boolean isInitialized = false;
|
||||
public final ItemStackHandler inventory = new ItemStackHandler(0);
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
|
||||
pTag.putInt("areaSize", areaSize);
|
||||
pTag.putFloat("gravityStrength", gravityStrength);
|
||||
super.saveAdditional(pTag, pRegistries);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
|
||||
areaSize = pTag.getInt("areaSize");
|
||||
gravityStrength = pTag.getFloat("gravityStrength");
|
||||
super.loadAdditional(pTag, pRegistries);
|
||||
}
|
||||
|
||||
public void setRadius(float r) {
|
||||
areaSize = (int) r;
|
||||
}
|
||||
|
||||
public void setStrength(float s) {
|
||||
gravityStrength = s;
|
||||
}
|
||||
|
||||
public void addGravityArea() {
|
||||
Level level = getLevel();
|
||||
if (level != null && level.isClientSide()) return;
|
||||
|
||||
BlockPos pos = this.getBlockPos();
|
||||
|
||||
GravityService.setGravityArea((ServerLevel) level, pos, gravityStrength, areaSize);
|
||||
}
|
||||
|
||||
public void removeGravityArea() {
|
||||
Level level = getLevel();
|
||||
if (level != null && level.isClientSide()) return;
|
||||
|
||||
BlockPos pos = this.getBlockPos();
|
||||
|
||||
GravityService.removeGravityArea((ServerLevel) level, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Level entityLevel, long time, BlockState blockState, BlockPos pos) {}
|
||||
|
||||
@Override
|
||||
public void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos) {}
|
||||
|
||||
@Override
|
||||
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {}
|
||||
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return isInitialized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void firstTick(Level level, BlockState state, BlockPos pos) { addGravityArea(); isInitialized = true; }
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||
return new GravityTestBlockMenu(i, inventory, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void sendUpdate() {
|
||||
removeGravityArea();
|
||||
addGravityArea();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||
return this.saveCustomOnly(registries);
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,8 @@ public class OxygenTestRenderer implements BlockEntityRenderer<OxygenTestBlockEn
|
||||
// If in debug mode, renders a model made from the blocks
|
||||
// that are currently returned by toBlockPositions(OxygenTestBlockEntity).
|
||||
public void render(OxygenTestBlockEntity be, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {
|
||||
if (true) return; // i think this is all deprecated now
|
||||
|
||||
// This bit's debug only, folks!
|
||||
if (!Minecraft.getInstance().gui.getDebugOverlay().showDebugScreen()) return;
|
||||
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
package net.xevianlight.aphelion.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public class DebugRenderUtils {
|
||||
|
||||
/// Utilities for dealing with longs instead of BlockPos
|
||||
/// I am not actually sure if this is faster or not. it probably is
|
||||
/// 99% sure that this breaks in edge cases
|
||||
public static class LongPos {
|
||||
private static final int PACKED_X_LENGTH = 26;
|
||||
private static final int PACKED_Y_LENGTH = 12;
|
||||
private static final int PACKED_Z_LENGTH = 26;
|
||||
private static final long PACKED_X_MASK = 67108863L;
|
||||
private static final long PACKED_Y_MASK = 4095L;
|
||||
private static final long PACKED_Z_MASK = 67108863L;
|
||||
private static final int Y_OFFSET = 0;
|
||||
private static final int Z_OFFSET = 12;
|
||||
private static final int X_OFFSET = 38;
|
||||
private static final long Y_MAGIC = PACKED_Y_MASK << Y_OFFSET;
|
||||
private static final long Z_MAGIC = PACKED_Z_MASK << Z_OFFSET;
|
||||
private static final long X_MAGIC = PACKED_X_MASK << X_OFFSET;
|
||||
|
||||
// no safeguard for the maximum values, but those are
|
||||
public static long above(long pos) {
|
||||
long y = (((pos & Y_MAGIC) >> Y_OFFSET) + 1) << Y_OFFSET;
|
||||
return (pos & (~Y_MAGIC)) | (y & Y_MAGIC);
|
||||
}
|
||||
|
||||
public static long below(long pos) {
|
||||
long y = (((pos & Y_MAGIC) >> Y_OFFSET) - 1) << Y_OFFSET;
|
||||
return (pos & (~Y_MAGIC)) | (y & Y_MAGIC);
|
||||
}
|
||||
|
||||
public static long north(long pos) {
|
||||
long z = (((pos & Z_MAGIC) >> Z_OFFSET) - 1) << Z_OFFSET;
|
||||
return (pos & (~Z_MAGIC)) | (z & Z_MAGIC);
|
||||
}
|
||||
|
||||
public static long south(long pos) {
|
||||
long z = (((pos & Z_MAGIC) >> Z_OFFSET) + 1) << Z_OFFSET;
|
||||
return (pos & (~Z_MAGIC)) | (z & Z_MAGIC);
|
||||
}
|
||||
|
||||
public static long east(long pos) {
|
||||
long x = (((pos & X_MAGIC) >> X_OFFSET) + 1) << X_OFFSET;
|
||||
return (pos & (~X_MAGIC)) | (x & X_MAGIC);
|
||||
}
|
||||
|
||||
public static long west(long pos) {
|
||||
long x = (((pos & X_MAGIC) >> X_OFFSET) - 1) << X_OFFSET;
|
||||
return (pos & (~X_MAGIC)) | (x & X_MAGIC);
|
||||
}
|
||||
|
||||
public static int getX(long pos) {
|
||||
return BlockPos.getX(pos);
|
||||
}
|
||||
|
||||
public static int getY(long pos) {
|
||||
return BlockPos.getY(pos);
|
||||
}
|
||||
|
||||
public static int getZ(long pos) {
|
||||
return BlockPos.getZ(pos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawSphere(PoseStack poseStack, VertexConsumer vc, Vector3f center, float radius) {
|
||||
|
||||
Matrix4f mat = poseStack.last().pose();
|
||||
|
||||
final int Y_SEGMENT_COUNT = 20;
|
||||
for (int segmentY=0; segmentY < Y_SEGMENT_COUNT; segmentY++) {
|
||||
double bottomAngle = (((double) segmentY / Y_SEGMENT_COUNT) - 0.5) * Math.PI;
|
||||
double topAngle = (((double) (segmentY+1) / Y_SEGMENT_COUNT) - 0.5) * Math.PI;
|
||||
float y0 = (float) Math.sin(bottomAngle) * radius + center.y();
|
||||
float y1 = (float) Math.sin(topAngle) * radius + center.y();
|
||||
float bottomRadius = (float) Math.cos(bottomAngle) * radius;
|
||||
float topRadius = (float) Math.cos(topAngle) * radius;
|
||||
|
||||
final int POLAR_SEGMENT_COUNT = 20;
|
||||
for (int segmentP = 0; segmentP < POLAR_SEGMENT_COUNT; segmentP++) {
|
||||
// "left" and "right" As viewed from outside the sphere
|
||||
double leftAngle = (((double) segmentP / POLAR_SEGMENT_COUNT) - 1) * 2 * Math.PI;
|
||||
double rightAngle = (((double) (segmentP+1) / POLAR_SEGMENT_COUNT) - 1) * 2 * Math.PI;
|
||||
// Points have to wind CCW, so 0->1->2->3 is CCW.
|
||||
// 0 and 1 use y0, 2 and 3 use y1.
|
||||
float x0, x1, x2, x3, z0, z1, z2, z3;
|
||||
|
||||
x0 = (float) Math.cos(leftAngle) * bottomRadius + center.x();
|
||||
x1 = (float) Math.cos(rightAngle) * bottomRadius + center.x();
|
||||
x2 = (float) Math.cos(rightAngle) * topRadius + center.x();
|
||||
x3 = (float) Math.cos(leftAngle) * topRadius + center.x();
|
||||
z0 = (float) Math.sin(leftAngle) * bottomRadius + center.z();
|
||||
z1 = (float) Math.sin(rightAngle) * bottomRadius + center.z();
|
||||
z2 = (float) Math.sin(rightAngle) * topRadius + center.z();
|
||||
z3 = (float) Math.sin(leftAngle) * topRadius + center.z();
|
||||
|
||||
// Draw the sphere quad
|
||||
quad(mat, vc,
|
||||
x0, y0, z0,
|
||||
x1, y0, z1,
|
||||
x2, y1, z2,
|
||||
x3, y1, z3,
|
||||
0.7f, 0.2f, 0.2f, 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sorry LOSERS, we only let FAST data structures in HERE.
|
||||
public static void drawBlockArea(PoseStack poseStack, VertexConsumer vc, LongOpenHashSet blocks) {
|
||||
|
||||
for (long p : blocks) {
|
||||
|
||||
|
||||
// Neighbor checks: only render faces exposed to non-oxygen
|
||||
boolean up = blocks.contains(LongPos.above(p));
|
||||
boolean down = blocks.contains(LongPos.below(p));
|
||||
boolean north = blocks.contains(LongPos.north(p));
|
||||
boolean south = blocks.contains(LongPos.south(p));
|
||||
boolean east = blocks.contains(LongPos.east(p));
|
||||
boolean west = blocks.contains(LongPos.west(p));
|
||||
|
||||
if (up && down && north && south && east && west) continue;
|
||||
|
||||
drawBlockFaces(poseStack, vc, p, up, down, north, south, east, west);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawBlockFaces(
|
||||
PoseStack poseStack, VertexConsumer vc, long posAsLong,
|
||||
boolean up, boolean down, boolean north, boolean south, boolean east, boolean west) {
|
||||
final float eps = 0.0025f;
|
||||
float x0 = LongPos.getX(posAsLong) + eps;
|
||||
float y0 = LongPos.getY(posAsLong) + eps;
|
||||
float z0 = LongPos.getZ(posAsLong) + eps;
|
||||
float x1 = LongPos.getX(posAsLong) + 1 - eps;
|
||||
float y1 = LongPos.getY(posAsLong) + 1 - eps;
|
||||
float z1 = LongPos.getZ(posAsLong) + 1 - eps;
|
||||
|
||||
// Color (ARGB-ish but as floats)
|
||||
float r = 0.2f, g = 0.8f, b = 1.0f, a = 0.18f;
|
||||
|
||||
Matrix4f mat = poseStack.last().pose();
|
||||
|
||||
// IMPORTANT: vertex winding should be consistent (counter-clockwise)
|
||||
if (!up) quad(mat, vc, x0,y1,z0, x1,y1,z0, x1,y1,z1, x0,y1,z1, r,g,b,a);
|
||||
if (!down) quad(mat, vc, x0,y0,z1, x1,y0,z1, x1,y0,z0, x0,y0,z0, r,g,b,a);
|
||||
|
||||
if (!north) quad(mat, vc, x1,y0,z0, x0,y0,z0, x0,y1,z0, x1,y1,z0, r,g,b,a);
|
||||
if (!south) quad(mat, vc, x0,y0,z1, x1,y0,z1, x1,y1,z1, x0,y1,z1, r,g,b,a);
|
||||
|
||||
if (!east) quad(mat, vc, x1,y0,z1, x1,y0,z0, x1,y1,z0, x1,y1,z1, r,g,b,a);
|
||||
if (!west) quad(mat, vc, x0,y0,z0, x0,y0,z1, x0,y1,z1, x0,y1,z0, r,g,b,a);
|
||||
}
|
||||
|
||||
public static void quad(
|
||||
Matrix4f mat, VertexConsumer vc,
|
||||
float x0, float y0, float z0,
|
||||
float x1, float y1, float z1,
|
||||
float x2, float y2, float z2,
|
||||
float x3, float y3, float z3,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
// POSITION_COLOR format: ONLY position + color.
|
||||
vc.addVertex(mat, x0, y0, z0).setColor(r, g, b, a);
|
||||
vc.addVertex(mat, x1, y1, z1).setColor(r, g, b, a);
|
||||
vc.addVertex(mat, x2, y2, z2).setColor(r, g, b, a);
|
||||
vc.addVertex(mat, x3, y3, z3).setColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package net.xevianlight.aphelion.client;
|
||||
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import it.unimi.dsi.fastutil.longs.Long2IntMap;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderStateShard;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.server.IntegratedServer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.core.saveddata.GravitySavedData;
|
||||
import net.xevianlight.aphelion.core.saveddata.types.GravityData;
|
||||
|
||||
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
|
||||
public class GravityDebugRender {
|
||||
// Untextured translucent quads (POSITION_COLOR only)
|
||||
private static final RenderType GRAVITY_FILL = RenderType.create(
|
||||
"aphelion_gravity_fill",
|
||||
DefaultVertexFormat.POSITION_COLOR,
|
||||
VertexFormat.Mode.QUADS,
|
||||
256,
|
||||
false,
|
||||
true,
|
||||
RenderType.CompositeState.builder()
|
||||
.setShaderState(RenderStateShard.POSITION_COLOR_SHADER)
|
||||
.setTransparencyState(RenderStateShard.TRANSLUCENT_TRANSPARENCY)
|
||||
.setCullState(RenderStateShard.NO_CULL)
|
||||
.setDepthTestState(RenderStateShard.LEQUAL_DEPTH_TEST)
|
||||
.setWriteMaskState(RenderStateShard.COLOR_DEPTH_WRITE)
|
||||
.createCompositeState(true)
|
||||
);
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLevel(RenderLevelStageEvent event) {
|
||||
// One stage only (pick one that exists and looks good)
|
||||
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS) return;
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.level == null || mc.player == null) return;
|
||||
if (!mc.gui.getDebugOverlay().showDebugScreen()) return;
|
||||
|
||||
PoseStack poseStack = event.getPoseStack();
|
||||
var cam = mc.gameRenderer.getMainCamera();
|
||||
var camPos = cam.getPosition();
|
||||
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(-camPos.x, -camPos.y, -camPos.z);
|
||||
|
||||
// I'm lazy, so i'm just gonna make this work on a singleplayer server and call it a day :P
|
||||
IntegratedServer singleplayer = mc.getSingleplayerServer();
|
||||
if (singleplayer == null) return;
|
||||
|
||||
MultiBufferSource.BufferSource bufferSource = mc.renderBuffers().bufferSource();
|
||||
VertexConsumer vc = bufferSource.getBuffer(GRAVITY_FILL);
|
||||
|
||||
for (Long2IntMap.Entry gravityEntry : GravitySavedData.get(singleplayer.getLevel(mc.level.dimension()))._debug_getGravityData().long2IntEntrySet()) {
|
||||
GravityData d = GravityData.unpack(gravityEntry.getIntValue());
|
||||
BlockPos p = BlockPos.of(gravityEntry.getLongKey());
|
||||
|
||||
DebugRenderUtils.drawSphere(poseStack, vc, p.getCenter().toVector3f(), d.getRadius());
|
||||
}
|
||||
|
||||
poseStack.popPose();
|
||||
bufferSource.endBatch(GRAVITY_FILL);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import net.neoforged.neoforge.client.event.RenderLevelStageEvent;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
|
||||
public final class OxygenDebugRender {
|
||||
|
||||
@@ -56,63 +58,9 @@ public final class OxygenDebugRender {
|
||||
MultiBufferSource.BufferSource bufferSource = mc.renderBuffers().bufferSource();
|
||||
VertexConsumer vc = bufferSource.getBuffer(OXYGEN_FILL);
|
||||
|
||||
// Render surface faces only (fast + pretty)
|
||||
for (long l : ClientOxygenCache.OXYGEN) {
|
||||
BlockPos p = BlockPos.of(l);
|
||||
drawSurfaceFaces(poseStack, vc, p);
|
||||
}
|
||||
DebugRenderUtils.drawBlockArea(poseStack, vc, ClientOxygenCache.OXYGEN);
|
||||
|
||||
poseStack.popPose();
|
||||
bufferSource.endBatch(OXYGEN_FILL);
|
||||
}
|
||||
|
||||
private static void drawSurfaceFaces(PoseStack poseStack, VertexConsumer vc, BlockPos p) {
|
||||
// Neighbor checks: only render faces exposed to non-oxygen
|
||||
boolean up = ClientOxygenCache.OXYGEN.contains(p.above().asLong());
|
||||
boolean down = ClientOxygenCache.OXYGEN.contains(p.below().asLong());
|
||||
boolean north = ClientOxygenCache.OXYGEN.contains(p.north().asLong());
|
||||
boolean south = ClientOxygenCache.OXYGEN.contains(p.south().asLong());
|
||||
boolean east = ClientOxygenCache.OXYGEN.contains(p.east().asLong());
|
||||
boolean west = ClientOxygenCache.OXYGEN.contains(p.west().asLong());
|
||||
|
||||
if (up && down && north && south && east && west) return;
|
||||
|
||||
final float eps = 0.0025f;
|
||||
float x0 = p.getX() + eps;
|
||||
float y0 = p.getY() + eps;
|
||||
float z0 = p.getZ() + eps;
|
||||
float x1 = p.getX() + 1 - eps;
|
||||
float y1 = p.getY() + 1 - eps;
|
||||
float z1 = p.getZ() + 1 - eps;
|
||||
|
||||
// Color (ARGB-ish but as floats)
|
||||
float r = 0.2f, g = 0.8f, b = 1.0f, a = 0.18f;
|
||||
|
||||
Matrix4f mat = poseStack.last().pose();
|
||||
|
||||
// IMPORTANT: vertex winding should be consistent (counter-clockwise)
|
||||
if (!up) quad(mat, vc, x0,y1,z0, x1,y1,z0, x1,y1,z1, x0,y1,z1, r,g,b,a);
|
||||
if (!down) quad(mat, vc, x0,y0,z1, x1,y0,z1, x1,y0,z0, x0,y0,z0, r,g,b,a);
|
||||
|
||||
if (!north) quad(mat, vc, x1,y0,z0, x0,y0,z0, x0,y1,z0, x1,y1,z0, r,g,b,a);
|
||||
if (!south) quad(mat, vc, x0,y0,z1, x1,y0,z1, x1,y1,z1, x0,y1,z1, r,g,b,a);
|
||||
|
||||
if (!east) quad(mat, vc, x1,y0,z1, x1,y0,z0, x1,y1,z0, x1,y1,z1, r,g,b,a);
|
||||
if (!west) quad(mat, vc, x0,y0,z0, x0,y0,z1, x0,y1,z1, x0,y1,z0, r,g,b,a);
|
||||
}
|
||||
|
||||
private static void quad(
|
||||
Matrix4f mat, VertexConsumer vc,
|
||||
float x0, float y0, float z0,
|
||||
float x1, float y1, float z1,
|
||||
float x2, float y2, float z2,
|
||||
float x3, float y3, float z3,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
// POSITION_COLOR format: ONLY position + color.
|
||||
vc.addVertex(mat, x0, y0, z0).setColor(r, g, b, a);
|
||||
vc.addVertex(mat, x1, y1, z1).setColor(r, g, b, a);
|
||||
vc.addVertex(mat, x2, y2, z2).setColor(r, g, b, a);
|
||||
vc.addVertex(mat, x3, y3, z3).setColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,9 @@ public class ModBlockEntities {
|
||||
BLOCK_ENTITIES.register("rocket_assembler_block_entity", () -> BlockEntityType.Builder.of(
|
||||
RocketAssemblerBlockEntity::new, ModBlocks.ROCKET_ASSEMBLER_BLOCK.get()).build(null)
|
||||
);
|
||||
|
||||
public static final Supplier<BlockEntityType<GravityTestBlockEntity>> GRAVITY_TEST_BLOCK_ENTITY =
|
||||
BLOCK_ENTITIES.register("gravity_test_block_entity", () -> BlockEntityType.Builder.of(
|
||||
GravityTestBlockEntity::new, ModBlocks.GRAVITY_TEST_BLOCK.get()).build(null)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.block.custom.*;
|
||||
import net.xevianlight.aphelion.block.dummy.VAFMultiblockDummyBlock;
|
||||
import net.xevianlight.aphelion.block.entity.custom.GravityTestBlockEntity;
|
||||
|
||||
public class ModBlocks {
|
||||
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(Aphelion.MOD_ID);
|
||||
@@ -20,4 +21,5 @@ public class ModBlocks {
|
||||
public static final DeferredBlock<Block> VAF_MULTIBLOCK_DUMMY_BLOCK = BLOCKS.register("vaf_dummy_block", () -> new VAFMultiblockDummyBlock(VAFMultiblockDummyBlock.getProperties()));
|
||||
public static final DeferredBlock<Block> OXYGEN_TEST_BLOCK = BLOCKS.register("oxygen_test_block", () -> new OxygenTestBlock(OxygenTestBlock.getProperties()));
|
||||
public static final DeferredBlock<Block> ROCKET_ASSEMBLER_BLOCK = BLOCKS.register("rocket_assemblerblock", () -> new RocketAssemblerBlock(RocketAssemblerBlock.getProperties()));
|
||||
public static final DeferredBlock<Block> GRAVITY_TEST_BLOCK = BLOCKS.register("gravity_test_block", () -> new GravityTestBlock(GravityTestBlock.getProperties()));
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ public static final DeferredItem<Item> MUSIC_DISC_BIT_SHIFT = ITEMS.register("mu
|
||||
public static final DeferredItem<BlockItem> ARC_FURNACE_CASING_BLOCK = ITEMS.register("arc_furnace_casing", () -> new BlockItem(ModBlocks.ARC_FURNACE_CASING_BLOCK.get(), ArcFurnaceCasingBlock.getItemProperties()));
|
||||
public static final DeferredItem<BlockItem> VACUUM_ARC_FURNACE_CONTROLLER = ITEMS.register("vacuum_arc_furnace_controller", () -> new BlockItem(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get(), VacuumArcFurnaceController.getItemProperties()));
|
||||
public static final DeferredItem<BlockItem> OXYGEN_TEST_BLOCK = ITEMS.register("oxygen_test_block", () -> new BlockItem(ModBlocks.OXYGEN_TEST_BLOCK.get(), new Item.Properties()));
|
||||
public static final DeferredItem<BlockItem> GRAVITY_TEST_BLOCK = ITEMS.register("gravity_test_block", () -> new BlockItem(ModBlocks.GRAVITY_TEST_BLOCK.get(), new Item.Properties()));
|
||||
public static final DeferredItem<BlockItem> LAUNCH_PAD = ITEMS.register("launch_pad", () -> new BlockItem(ModBlocks.LAUNCH_PAD.get(), LaunchPad.getItemProperties()));
|
||||
// public static final DeferredItem<BlockItem> VAF_MULTIBLOCK_DUMMY_BLOCK = ITEMS.register("vaf_multiblock_dummy_block", () -> new BlockItem(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get(), VAFMultiblockDummyBlock.getItemProperties()));
|
||||
}
|
||||
|
||||
@@ -32,12 +32,18 @@ import java.util.List;
|
||||
*/
|
||||
public class GravitySavedData extends SavedData {
|
||||
|
||||
private Level level;
|
||||
|
||||
private final Long2IntOpenHashMap gravityData = new Long2IntOpenHashMap();
|
||||
|
||||
private static final String NAME = "aphelion_gravity";
|
||||
|
||||
public static GravitySavedData create() {
|
||||
return new GravitySavedData();
|
||||
public static GravitySavedData create(Level level) {
|
||||
return new GravitySavedData(level);
|
||||
}
|
||||
|
||||
public GravitySavedData(Level level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,18 +66,18 @@ public class GravitySavedData extends SavedData {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static GravitySavedData load(CompoundTag tag, HolderLookup.Provider lookupProvider) {
|
||||
GravitySavedData data = create();
|
||||
public static GravitySavedData load(CompoundTag tag, HolderLookup.Provider lookupProvider, Level level) {
|
||||
GravitySavedData data = new GravitySavedData(level);
|
||||
|
||||
if (!tag.contains("Position", Tag.TAG_LONG_ARRAY) || !tag.contains("Value", Tag.TAG_INT_ARRAY)) { return data; }
|
||||
if (!tag.contains("Position", Tag.TAG_LONG_ARRAY) || !tag.contains("Value", Tag.TAG_INT_ARRAY)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
long[] positions = tag.getLongArray("Position");
|
||||
int[] values = tag.getIntArray("Value");
|
||||
|
||||
int length = Math.min(positions.length, values.length);
|
||||
|
||||
data.gravityData.ensureCapacity(length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
data.gravityData.put(positions[i], values[i]);
|
||||
}
|
||||
@@ -81,7 +87,7 @@ public class GravitySavedData extends SavedData {
|
||||
|
||||
private static final int ABSENT = Integer.MIN_VALUE;
|
||||
|
||||
public @Nullable GravityData getGravityRegionData (Level level, BlockPos center) {
|
||||
public @Nullable GravityData getGravityRegionData (BlockPos center) {
|
||||
GravityData data = GravityData.unpack(gravityData.getOrDefault(center.asLong(), ABSENT));
|
||||
return data.pack() == ABSENT ? null : data;
|
||||
}
|
||||
@@ -94,6 +100,9 @@ public class GravitySavedData extends SavedData {
|
||||
gravityData.put(pos.asLong(), data.pack());
|
||||
}
|
||||
|
||||
public Long2IntOpenHashMap _debug_getGravityData() {
|
||||
return gravityData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -115,7 +124,7 @@ public class GravitySavedData extends SavedData {
|
||||
* Returns the strongest acceleration among all gravity regions that overlap this block position
|
||||
*/
|
||||
public float getGravityMax (BlockPos pos) {
|
||||
float max = 0;
|
||||
float max = -1;
|
||||
|
||||
List<GravityData> regions = getGravityRegions(pos);
|
||||
|
||||
@@ -124,6 +133,10 @@ public class GravitySavedData extends SavedData {
|
||||
if (accel > max) max = accel;
|
||||
}
|
||||
|
||||
if (max == -1) {
|
||||
max = defaultGravity(this.level);
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
@@ -158,7 +171,10 @@ public class GravitySavedData extends SavedData {
|
||||
|
||||
public static GravitySavedData get(ServerLevel level) {
|
||||
return level.getDataStorage().computeIfAbsent(
|
||||
new Factory<>(GravitySavedData::create, GravitySavedData::load),
|
||||
new Factory<>(
|
||||
() -> new GravitySavedData(level),
|
||||
(tag, provider) -> GravitySavedData.load(tag, provider, level)
|
||||
),
|
||||
NAME
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ public class GravityData {
|
||||
private float accel;
|
||||
private float radius;
|
||||
|
||||
public static final float DEFAULT_GRAVITY = 9.80665f; // 1G
|
||||
public static final float ONE_G = 9.80665f;
|
||||
public static final float DEFAULT_GRAVITY = ONE_G; // 1G
|
||||
public static final float GRAVITY_PRECISION = 100.0f;
|
||||
public static final float RADIUS_PRECISION = 100.0f;
|
||||
public static final float MAX_RADIUS = Short.MAX_VALUE / RADIUS_PRECISION;
|
||||
|
||||
@@ -26,6 +26,8 @@ public class ModBlockLootTableProvider extends BlockLootSubProvider {
|
||||
dropSelf(ModBlocks.OXYGEN_TEST_BLOCK.get());
|
||||
dropOther(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get(), ItemStack.EMPTY.getItem());
|
||||
dropSelf(ModBlocks.LAUNCH_PAD.get());
|
||||
dropSelf(ModBlocks.GRAVITY_TEST_BLOCK.get());
|
||||
dropSelf(ModBlocks.ROCKET_ASSEMBLER_BLOCK.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,7 +32,9 @@ public class ModBlockStateProvider extends BlockStateProvider {
|
||||
// blockItem(ModBlocks.LAUNCH_PAD);
|
||||
|
||||
blockItem(ModBlocks.ARC_FURNACE_CASING_BLOCK);
|
||||
|
||||
blockWithItem(ModBlocks.OXYGEN_TEST_BLOCK);
|
||||
blockWithItem(ModBlocks.GRAVITY_TEST_BLOCK);
|
||||
}
|
||||
|
||||
private void blockWithItem(DeferredBlock<?> deferredBlock) {
|
||||
|
||||
@@ -13,10 +13,14 @@ import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
|
||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||
import net.xevianlight.aphelion.network.ClientPlayerStateUpdateHandler;
|
||||
import net.xevianlight.aphelion.network.RocketPayloadHandlers;
|
||||
import net.xevianlight.aphelion.network.PartitionPayloadHandler;
|
||||
import net.xevianlight.aphelion.network.UpdateGravityTestBlockHandler;
|
||||
import net.xevianlight.aphelion.network.packet.ClientPlayerStateUpdatePacket;
|
||||
import net.xevianlight.aphelion.network.packet.PartitionPayload;
|
||||
import net.xevianlight.aphelion.network.packet.RocketLaunchPayload;
|
||||
import net.xevianlight.aphelion.network.packet.UpdateGravityTestBlockPacket;
|
||||
|
||||
@EventBusSubscriber(modid = Aphelion.MOD_ID)
|
||||
public class ModBusEvents {
|
||||
@@ -49,5 +53,16 @@ public class ModBusEvents {
|
||||
RocketPayloadHandlers::handleRocketLaunch
|
||||
);
|
||||
|
||||
registrar.playToClient(
|
||||
ClientPlayerStateUpdatePacket.TYPE,
|
||||
ClientPlayerStateUpdatePacket.STREAM_CODEC,
|
||||
ClientPlayerStateUpdateHandler::handleDataOnMain
|
||||
);
|
||||
|
||||
registrar.playToServer(
|
||||
UpdateGravityTestBlockPacket.TYPE,
|
||||
UpdateGravityTestBlockPacket.STREAM_CODEC,
|
||||
UpdateGravityTestBlockHandler::handleDataOnMain
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package net.xevianlight.aphelion.mixins.common;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.attachment.AttachmentHolder;
|
||||
import net.xevianlight.aphelion.systems.GravityService;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
import org.spongepowered.asm.util.Locals;
|
||||
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin extends AttachmentHolder {
|
||||
|
||||
|
||||
@Shadow
|
||||
public float fallDistance;
|
||||
|
||||
// @At("RETURN") injects at all points IMMEDIATELY before a "return" opcode.
|
||||
// Immediately before means IMMEDIATELY BEFORE,
|
||||
// so even in a method like:
|
||||
//
|
||||
// return gravity;
|
||||
//
|
||||
// What's ACTUALLY happening is:
|
||||
//
|
||||
// $value = gravity;
|
||||
// return $value;
|
||||
//
|
||||
// So, when we inject, we get:
|
||||
//
|
||||
// $value = gravity;
|
||||
// [RETURN INJECT POINT]
|
||||
// return $value;
|
||||
//
|
||||
// so we get to edit $value.
|
||||
@Inject(method = "getGravity", at = @At("RETURN"), cancellable = true)
|
||||
public void aphelion$getGravity(CallbackInfoReturnable<Double> cir) {
|
||||
cir.setReturnValue(cir.getReturnValue() * GravityService.getGravityFactor((Entity) (Object) this));
|
||||
}
|
||||
|
||||
// Should only break if the code that increases fall distance is moved outside Entity$checkFallDamage.
|
||||
@WrapMethod(method = "checkFallDamage")
|
||||
public void aphelion$checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos, Operation<Void> original) {
|
||||
float prevFallDistance = this.fallDistance;
|
||||
|
||||
original.call(y, onGround, state, pos);
|
||||
|
||||
float newFallDistance = this.fallDistance;
|
||||
if (newFallDistance > prevFallDistance && newFallDistance > 0) {
|
||||
float fallDistanceGained = newFallDistance - prevFallDistance;
|
||||
this.fallDistance = prevFallDistance + (fallDistanceGained * Math.min(GravityService.getGravityFactor((Entity) (Object) this), 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import net.minecraft.world.entity.Entity;
|
||||
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 net.xevianlight.aphelion.systems.GravityService;
|
||||
import net.xevianlight.aphelion.systems.OxygenService;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -26,4 +28,10 @@ public abstract class LivingEntityMixin extends Entity {
|
||||
OxygenService.entityTick(level, entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "travel", at = @At("HEAD"))
|
||||
public void aphelion$travel(Vec3 travelVector, CallbackInfo ci) {
|
||||
// temporarily disabled in favor of aphelion$getGravity mixin
|
||||
//if (this.isControlledByLocalInstance()) GravityService.onEntityTravel(level(), (LivingEntity) (Object) this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.xevianlight.aphelion.network;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.xevianlight.aphelion.core.saveddata.types.GravityData;
|
||||
import net.xevianlight.aphelion.systems.GravityService;
|
||||
import net.xevianlight.aphelion.systems.OxygenService;
|
||||
|
||||
/// Read-only player state object; updated by a server packet every so often
|
||||
public record ClientPlayerState(boolean oxygen, float gravity, float temperature) {
|
||||
// Default player state
|
||||
private static ClientPlayerState localData = new ClientPlayerState(true, GravityData.DEFAULT_GRAVITY * 0.5f, 50f);
|
||||
|
||||
public static void updateState(ClientPlayerState newData) {
|
||||
onStateUpdate(localData, newData);
|
||||
localData = newData;
|
||||
}
|
||||
|
||||
public static ClientPlayerState getServerStateOf(Player player) {
|
||||
return new ClientPlayerState(OxygenService.hasOxygen(player), GravityService.getGravityAccel(player), 50f);
|
||||
}
|
||||
|
||||
/// For things like playing SFX, VFX, etc. etc.
|
||||
public static void onStateUpdate(ClientPlayerState oldData, ClientPlayerState newData) {
|
||||
// TODO: add sfx
|
||||
if (!oldData.oxygen() && newData.oxygen()) {
|
||||
// On oxygen gained
|
||||
}
|
||||
if (oldData.oxygen() && !newData.oxygen()) {
|
||||
// On oxygen removed
|
||||
}
|
||||
if (newData.gravity() - 0.25f > oldData.gravity()) {
|
||||
// On gravity increased by > 0.25
|
||||
}
|
||||
if (oldData.gravity() - 0.25f > newData.gravity()) {
|
||||
// On gravity decreased by > 0.25
|
||||
}
|
||||
}
|
||||
|
||||
public static ClientPlayerState getLocalData() {
|
||||
return localData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.xevianlight.aphelion.network;
|
||||
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||
import net.xevianlight.aphelion.network.packet.ClientPlayerStateUpdatePacket;
|
||||
|
||||
public class ClientPlayerStateUpdateHandler {
|
||||
|
||||
public static void handleDataOnMain(ClientPlayerStateUpdatePacket packet, IPayloadContext context) {
|
||||
context.enqueueWork(() -> ClientPlayerState.updateState(new ClientPlayerState(packet.oxygen(), packet.gravity(), packet.temp())));
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,16 @@ package net.xevianlight.aphelion.network;
|
||||
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||
import net.neoforged.neoforge.event.tick.ServerTickEvent;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.entites.vehicles.RocketEntity;
|
||||
import net.xevianlight.aphelion.network.packet.ClientPlayerStateUpdatePacket;
|
||||
import net.xevianlight.aphelion.network.packet.RocketLaunchPayload;
|
||||
|
||||
import net.xevianlight.aphelion.client.AphelionClient;
|
||||
@@ -27,4 +31,17 @@ public final class KeyNetwork {
|
||||
PacketDistributor.sendToServer(new RocketLaunchPayload(rocket.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onServerTick(ServerTickEvent.Post event) {
|
||||
int FREQ = 4;
|
||||
for (ServerPlayer p : event.getServer().getPlayerList().getPlayers()) {
|
||||
if (p.tickCount % FREQ == 0) {
|
||||
ClientPlayerState state = ClientPlayerState.getServerStateOf(p);
|
||||
|
||||
PacketDistributor.sendToPlayer(p, new ClientPlayerStateUpdatePacket(state.oxygen(), state.gravity(), state.temperature()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.xevianlight.aphelion.network;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||
import net.xevianlight.aphelion.block.entity.custom.GravityTestBlockEntity;
|
||||
import net.xevianlight.aphelion.network.packet.UpdateGravityTestBlockPacket;
|
||||
|
||||
public class UpdateGravityTestBlockHandler {
|
||||
public static void handleDataOnMain(UpdateGravityTestBlockPacket packet, IPayloadContext context) {
|
||||
context.enqueueWork(() -> {
|
||||
BlockPos pos = packet.pos();
|
||||
float radius = packet.radius();
|
||||
float strength = packet.strength();
|
||||
|
||||
Level level = context.player().level();
|
||||
if (level.getBlockEntity(pos) instanceof GravityTestBlockEntity blockEntity) {
|
||||
blockEntity.setRadius(radius);
|
||||
blockEntity.setStrength(strength);
|
||||
blockEntity.sendUpdate();
|
||||
level.sendBlockUpdated(pos, level.getBlockState(pos), level.getBlockState(pos), Block.UPDATE_ALL);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package net.xevianlight.aphelion.network.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.network.codec.ByteBufCodecs;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
|
||||
public record ClientPlayerStateUpdatePacket(boolean oxygen, float gravity, float temp) implements CustomPacketPayload {
|
||||
public static final CustomPacketPayload.Type<ClientPlayerStateUpdatePacket> TYPE = new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "player_state_update"));
|
||||
|
||||
public static final StreamCodec<ByteBuf, ClientPlayerStateUpdatePacket> STREAM_CODEC = StreamCodec.composite(
|
||||
ByteBufCodecs.BOOL,
|
||||
ClientPlayerStateUpdatePacket::oxygen,
|
||||
ByteBufCodecs.FLOAT,
|
||||
ClientPlayerStateUpdatePacket::gravity,
|
||||
ByteBufCodecs.FLOAT,
|
||||
ClientPlayerStateUpdatePacket::temp,
|
||||
ClientPlayerStateUpdatePacket::new
|
||||
);
|
||||
|
||||
@Override
|
||||
public CustomPacketPayload.Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package net.xevianlight.aphelion.network.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.codec.ByteBufCodecs;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
|
||||
public record UpdateGravityTestBlockPacket(BlockPos pos, float radius, float strength) implements CustomPacketPayload {
|
||||
|
||||
public static final CustomPacketPayload.Type<UpdateGravityTestBlockPacket> TYPE =
|
||||
new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "update_oxygen_test_block"));
|
||||
|
||||
public static final StreamCodec<ByteBuf, UpdateGravityTestBlockPacket> STREAM_CODEC = StreamCodec.composite(
|
||||
BlockPos.STREAM_CODEC,
|
||||
UpdateGravityTestBlockPacket::pos,
|
||||
ByteBufCodecs.FLOAT,
|
||||
UpdateGravityTestBlockPacket::radius,
|
||||
ByteBufCodecs.FLOAT,
|
||||
UpdateGravityTestBlockPacket::strength,
|
||||
UpdateGravityTestBlockPacket::new
|
||||
);
|
||||
|
||||
@Override
|
||||
public CustomPacketPayload.Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package net.xevianlight.aphelion.screen;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.BrewingStandMenu;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.neoforged.neoforge.items.SlotItemHandler;
|
||||
import net.xevianlight.aphelion.block.entity.custom.GravityTestBlockEntity;
|
||||
import net.xevianlight.aphelion.block.entity.custom.TestBlockEntity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class GravityTestBlockMenu extends AbstractContainerMenu {
|
||||
public final GravityTestBlockEntity blockEntity;
|
||||
private final Level level;
|
||||
|
||||
public GravityTestBlockMenu(int i, Inventory inventory, FriendlyByteBuf extraData) {
|
||||
this(i, inventory, inventory.player.level().getBlockEntity(extraData.readBlockPos()));
|
||||
}
|
||||
|
||||
public GravityTestBlockMenu(int i, Inventory inventory, BlockEntity blockEntity) {
|
||||
super(ModMenuTypes.GRAVITY_TEST_BLOCK_MENU.get(), i);
|
||||
this.blockEntity = ((GravityTestBlockEntity) blockEntity);
|
||||
this.level = inventory.player.level();
|
||||
|
||||
// Init stuff
|
||||
addPlayerInventory(inventory);
|
||||
addPlayerHotbar(inventory);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons
|
||||
// must assign a slot number to each of the slots used by the GUI.
|
||||
// For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar.
|
||||
// Each time we add a Slot to the container, it automatically increases the slotIndex, which means
|
||||
// 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8)
|
||||
// 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35)
|
||||
// 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8)
|
||||
private static final int HOTBAR_SLOT_COUNT = 9;
|
||||
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
|
||||
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
|
||||
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
|
||||
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
|
||||
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
|
||||
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
|
||||
|
||||
// THIS YOU HAVE TO DEFINE!
|
||||
private static final int TE_INVENTORY_SLOT_COUNT = 0; // must be the number of slots you have!
|
||||
@Override
|
||||
public @NotNull ItemStack quickMoveStack(Player playerIn, int pIndex) {
|
||||
Slot sourceSlot = slots.get(pIndex);
|
||||
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
|
||||
ItemStack sourceStack = sourceSlot.getItem();
|
||||
ItemStack copyOfSourceStack = sourceStack.copy();
|
||||
|
||||
// Check if the slot clicked is one of the vanilla container slots
|
||||
if (pIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
|
||||
// This is a vanilla container slot so merge the stack into the tile inventory
|
||||
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
|
||||
+ TE_INVENTORY_SLOT_COUNT, false)) {
|
||||
blockEntity.sendUpdate();
|
||||
return ItemStack.EMPTY; // EMPTY_ITEM
|
||||
}
|
||||
} else if (pIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
|
||||
// This is a TE slot so merge the stack into the players inventory
|
||||
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
|
||||
blockEntity.sendUpdate();
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else {
|
||||
System.out.println("Invalid slotIndex:" + pIndex);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
// If stack size == 0 (the entire stack was moved) set slot contents to null
|
||||
if (sourceStack.getCount() == 0) {
|
||||
sourceSlot.set(ItemStack.EMPTY);
|
||||
blockEntity.sendUpdate();
|
||||
} else {
|
||||
blockEntity.sendUpdate();
|
||||
sourceSlot.setChanged();
|
||||
}
|
||||
sourceSlot.onTake(playerIn, sourceStack);
|
||||
blockEntity.sendUpdate();
|
||||
return copyOfSourceStack;
|
||||
}
|
||||
|
||||
private void addPlayerInventory(Inventory playerInventory) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int l = 0; l < 9; ++l) {
|
||||
this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPlayerHotbar(Inventory playerInventory) {
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package net.xevianlight.aphelion.screen;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.StringWidget;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.client.gui.screens.inventory.FurnaceScreen;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
import net.xevianlight.aphelion.network.packet.UpdateGravityTestBlockPacket;
|
||||
|
||||
public class GravityTestBlockScreen extends AbstractContainerScreen<GravityTestBlockMenu> {
|
||||
|
||||
private static final ResourceLocation GUI_TEXTURE =
|
||||
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "textures/gui/gravity_test_block/gui.png");
|
||||
|
||||
public GravityTestBlockScreen(GravityTestBlockMenu menu, Inventory playerInventory, Component title) {
|
||||
super(menu, playerInventory, title);
|
||||
}
|
||||
|
||||
private StringWidget gravityWidget;
|
||||
private StringWidget rangeWidget;
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
// Gets rid of labels
|
||||
this.inventoryLabelY = 73;
|
||||
this.titleLabelY = 5;
|
||||
|
||||
// Increase Gravity
|
||||
this.addRenderableWidget(Button.builder(Component.literal("+"), (button) -> {
|
||||
PacketDistributor.sendToServer(new UpdateGravityTestBlockPacket(menu.blockEntity.getBlockPos(), menu.blockEntity.areaSize, menu.blockEntity.gravityStrength + 0.1f));
|
||||
}).bounds(this.leftPos + 7, this.topPos + 30, 9, 9).build());
|
||||
// Decrease Gravity
|
||||
this.addRenderableWidget(Button.builder(Component.literal("-"), (button) -> {
|
||||
PacketDistributor.sendToServer(new UpdateGravityTestBlockPacket(menu.blockEntity.getBlockPos(), menu.blockEntity.areaSize, menu.blockEntity.gravityStrength - 0.1f));
|
||||
}).bounds(this.leftPos + 19, this.topPos + 30, 9, 9).build());
|
||||
// Increase Radius
|
||||
this.addRenderableWidget(Button.builder(Component.literal("+"), (button) -> {
|
||||
PacketDistributor.sendToServer(new UpdateGravityTestBlockPacket(menu.blockEntity.getBlockPos(), menu.blockEntity.areaSize + 1, menu.blockEntity.gravityStrength));
|
||||
}).bounds(this.leftPos + 135, this.topPos + 32, 9, 9).build());
|
||||
// Decrease Radius
|
||||
this.addRenderableWidget(Button.builder(Component.literal("-"), (button) -> {
|
||||
PacketDistributor.sendToServer(new UpdateGravityTestBlockPacket(menu.blockEntity.getBlockPos(), menu.blockEntity.areaSize - 1, menu.blockEntity.gravityStrength));
|
||||
}).bounds(this.leftPos + 147, this.topPos + 32, 9, 9).build());
|
||||
|
||||
// Current Gravity
|
||||
gravityWidget = new StringWidget(
|
||||
this.leftPos + 11,
|
||||
this.topPos+46,
|
||||
26,
|
||||
9,
|
||||
Component.literal("" + menu.blockEntity.gravityStrength),
|
||||
this.font);
|
||||
this.addRenderableWidget(gravityWidget);
|
||||
|
||||
// Current Radius
|
||||
rangeWidget = new StringWidget(
|
||||
this.leftPos + 139,
|
||||
this.topPos+46,
|
||||
26,
|
||||
9,
|
||||
Component.literal("" + menu.blockEntity.areaSize),
|
||||
this.font);
|
||||
this.addRenderableWidget(rangeWidget);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.setShaderTexture(0, GUI_TEXTURE);
|
||||
int x = (width - imageWidth) / 2;
|
||||
int y = (height - imageHeight) / 2;
|
||||
|
||||
pGuiGraphics.blit(GUI_TEXTURE, x, y, 0, 0, imageWidth, imageHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) {
|
||||
renderBackground(guiGraphics, mouseX, mouseY, delta);
|
||||
super.render(guiGraphics, mouseX, mouseY, delta);
|
||||
renderTooltip(guiGraphics, mouseX, mouseY);
|
||||
gravityWidget.setMessage(Component.literal(String.format("%.1f", menu.blockEntity.gravityStrength)));
|
||||
rangeWidget.setMessage(Component.literal("" + menu.blockEntity.areaSize));
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import net.neoforged.neoforge.registries.DeferredHolder;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import net.xevianlight.aphelion.Aphelion;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class ModMenuTypes {
|
||||
public static final DeferredRegister<MenuType<?>> MENUS =
|
||||
DeferredRegister.create(Registries.MENU, Aphelion.MOD_ID);
|
||||
@@ -23,6 +25,9 @@ public class ModMenuTypes {
|
||||
public static DeferredHolder<MenuType<?>,MenuType<VacuumArcFurnaceMenu>> VACUUM_ARC_FURNACE_MENU =
|
||||
registerMenuType("vacuum_arc_furnace_menu", VacuumArcFurnaceMenu::new);
|
||||
|
||||
public static DeferredHolder<MenuType<?>,MenuType<GravityTestBlockMenu>> GRAVITY_TEST_BLOCK_MENU =
|
||||
registerMenuType("gravity_test_block_menu", GravityTestBlockMenu::new);
|
||||
|
||||
private static <T extends AbstractContainerMenu>DeferredHolder<MenuType<?>, MenuType<T>> registerMenuType(String name,
|
||||
IContainerFactory<T> factory) {
|
||||
return MENUS.register(name, () -> IMenuTypeExtension.create(factory));
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package net.xevianlight.aphelion.systems;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.xevianlight.aphelion.network.ClientPlayerState;
|
||||
import net.xevianlight.aphelion.core.saveddata.GravitySavedData;
|
||||
import net.xevianlight.aphelion.core.saveddata.types.GravityData;
|
||||
|
||||
public class GravityService {
|
||||
|
||||
public static void setGravityArea(ServerLevel level, BlockPos pos, float accel, int radius) {
|
||||
GravitySavedData.get(level).setGravityRegion(pos, new GravityData(accel, radius));
|
||||
}
|
||||
|
||||
public static void removeGravityArea(ServerLevel level, BlockPos pos) {
|
||||
GravitySavedData.get(level).removeGravityRegion(pos);
|
||||
}
|
||||
|
||||
public static float getGravityAccel(Level level, BlockPos pos) {
|
||||
if (level.isClientSide) {
|
||||
// Pull from the client data b/c we can't access the server's saved data
|
||||
return ClientPlayerState.getLocalData().gravity();
|
||||
}
|
||||
// TODO: maybe change this based on how stuff pans out
|
||||
var gravity = GravitySavedData.get((ServerLevel) level).getGravityMax(pos);
|
||||
|
||||
return gravity;
|
||||
}
|
||||
|
||||
public static float getGravityAccel(Entity entity) {
|
||||
// Not sure if this is at the entity's feet, head, or the middle... research later
|
||||
// Blockpos is from entity's feet ~Xev
|
||||
BlockPos entityBlockPos = BlockPos.containing(entity.getX(), entity.getY(), entity.getZ());
|
||||
return getGravityAccel(entity.level(), entityBlockPos);
|
||||
}
|
||||
|
||||
public static float getGravityFactor(Entity entity) {
|
||||
float gravityAccelReal = getGravityAccel(entity);
|
||||
|
||||
// How many times normal gravity you're experiencing.
|
||||
// "normal gravity" varies across different entities. Thankfully, minecraft slaps a "protected" status
|
||||
// on LivingEntity.getGravity(), so i graciously get to go fuck myself and not care.
|
||||
// Players are 0.08 units/second/travel() of gravity (from what i've gathered)
|
||||
return gravityAccelReal / GravityData.ONE_G;
|
||||
}
|
||||
|
||||
/// Called by LivingEntity$travel mixin
|
||||
public static void onEntityTravel(Level level, LivingEntity entity) {
|
||||
if (
|
||||
entity.isFallFlying() || entity.isInLiquid() ||
|
||||
entity.isUnderWater() ||
|
||||
entity.hasEffect(MobEffects.SLOW_FALLING)
|
||||
) return;
|
||||
|
||||
float gravityAccelReal = getGravityAccel(entity);
|
||||
|
||||
// How many times normal gravity you're experiencing.
|
||||
// "normal gravity" varies across different entities. Thankfully, minecraft slaps a "protected" status
|
||||
// on LivingEntity.getGravity(), so i graciously get to go fuck myself and not care.
|
||||
// Players are 0.08 units/second/travel() of gravity (from what i've gathered)
|
||||
float gravityFactor = gravityAccelReal / GravityData.ONE_G;
|
||||
|
||||
// NOTE: this might cause certain entities to fly into the stratosphere at ultra low gravity,
|
||||
// seeing as this isn't the same for all entities.
|
||||
// Thankfully, though, this should have no effect on anything at default gravity.
|
||||
float baseGameGravityAccel = 0.08f;
|
||||
float translatedAccel = baseGameGravityAccel * gravityFactor;
|
||||
|
||||
Vec3 currentVelocity = entity.getDeltaMovement();
|
||||
// add baseGameGravity to cancel normal gravity, then subtract the new gravity
|
||||
if (translatedAccel > 0) entity.setDeltaMovement(currentVelocity.x(), currentVelocity.y() + (baseGameGravityAccel - translatedAccel), currentVelocity.z());
|
||||
else entity.setDeltaMovement(currentVelocity.x(), currentVelocity.y() + baseGameGravityAccel, currentVelocity.z());
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
"package": "net.xevianlight.aphelion.mixins",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"mixins": [
|
||||
"common.EntityMixin",
|
||||
"common.LivingEntityMixin"
|
||||
],
|
||||
"client": [
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 280 B |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 17 KiB |
@@ -2,6 +2,6 @@
|
||||
"dimension": "minecraft:overworld",
|
||||
"orbit_distance": 1,
|
||||
"star_system": "aphelon:sol",
|
||||
"gravity": 1,
|
||||
"gravity": 9.8,
|
||||
"oxygen": false
|
||||
}
|
||||
Reference in New Issue
Block a user