mirror of
https://github.com/XevianLight/Aphelion.git
synced 2026-05-11 01:50:56 +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-02-06T10:36:07.5023829 Loot Tables
|
||||||
// 1.21.1 2026-01-26T19:04:46.4976369 Loot Tables
|
|
||||||
69d8318ddba171526d1fabb87d9d93548ed8598e data/aphelion/loot_table/blocks/arc_furnace_casing.json
|
69d8318ddba171526d1fabb87d9d93548ed8598e data/aphelion/loot_table/blocks/arc_furnace_casing.json
|
||||||
05f08985e601d30116f67e2f07b48b03b40cdca6 data/aphelion/loot_table/blocks/block_steel.json
|
05f08985e601d30116f67e2f07b48b03b40cdca6 data/aphelion/loot_table/blocks/block_steel.json
|
||||||
ff43a9c3741faf10b1e156a7a74d5cfb035cc118 data/aphelion/loot_table/blocks/dimension_changer.json
|
ff43a9c3741faf10b1e156a7a74d5cfb035cc118 data/aphelion/loot_table/blocks/dimension_changer.json
|
||||||
b63130d9c10485676303d729807b6fcaac080294 data/aphelion/loot_table/blocks/electric_arc_furnace.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
|
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
|
1ab50c99e9f478840b9d003fd56ebdcab12fbbce data/aphelion/loot_table/blocks/test_block.json
|
||||||
7d8eeb99a1bc942a6e2cf292b21fd4534062b5ab data/aphelion/loot_table/blocks/vacuum_arc_furnace_controller.json
|
7d8eeb99a1bc942a6e2cf292b21fd4534062b5ab data/aphelion/loot_table/blocks/vacuum_arc_furnace_controller.json
|
||||||
797bf9839d79e08b4832c9eaf3cb303b0471ed0c data/aphelion/loot_table/blocks/vaf_dummy_block.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-02-06T10:36:07.5013847 Block States: aphelion
|
||||||
// 1.21.1 2026-01-26T20:40:43.8251623 Block States: aphelion
|
|
||||||
851ff42f7b21dec86107c8e0cefb3934ae4ebc08 assets/aphelion/blockstates/block_steel.json
|
851ff42f7b21dec86107c8e0cefb3934ae4ebc08 assets/aphelion/blockstates/block_steel.json
|
||||||
30b9c0efd7aaadb5412d98e4568f98b3632adbb9 assets/aphelion/blockstates/dimension_changer.json
|
30b9c0efd7aaadb5412d98e4568f98b3632adbb9 assets/aphelion/blockstates/dimension_changer.json
|
||||||
cb4287104006c80c8396b290ab5258df65d62cef assets/aphelion/blockstates/electric_arc_furnace.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
|
28131a570d3666b7f323de4ad8a69e52ceec92e2 assets/aphelion/blockstates/oxygen_test_block.json
|
||||||
b86c50fddcf6c8c6c19cb748529239d5962a3ede assets/aphelion/blockstates/test_block.json
|
b86c50fddcf6c8c6c19cb748529239d5962a3ede assets/aphelion/blockstates/test_block.json
|
||||||
a810b97f4dace35d026f28d96cb9c47c93600d75 assets/aphelion/models/block/block_steel.json
|
a810b97f4dace35d026f28d96cb9c47c93600d75 assets/aphelion/models/block/block_steel.json
|
||||||
2d3592b7ab7132908709243e97540151e0fb762e assets/aphelion/models/block/dimension_changer.json
|
2d3592b7ab7132908709243e97540151e0fb762e assets/aphelion/models/block/dimension_changer.json
|
||||||
5f7e8674070f31a63875b5d6147153bfa0eef61a assets/aphelion/models/block/electric_arc_furnace.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
|
746f23f150a01524ad03cbd1eb822bfbb7cf453b assets/aphelion/models/block/oxygen_test_block.json
|
||||||
e0971228b4a1c4bc9dbab58a7dacdc3ae6037e02 assets/aphelion/models/block/test_block.json
|
e0971228b4a1c4bc9dbab58a7dacdc3ae6037e02 assets/aphelion/models/block/test_block.json
|
||||||
cdc831b0f1c462be64825fd34bd446e5b95afac6 assets/aphelion/models/item/arc_furnace_casing.json
|
cdc831b0f1c462be64825fd34bd446e5b95afac6 assets/aphelion/models/item/arc_furnace_casing.json
|
||||||
3599f9037eb2f66de1765318b97ab564c3eae92f assets/aphelion/models/item/block_steel.json
|
3599f9037eb2f66de1765318b97ab564c3eae92f assets/aphelion/models/item/block_steel.json
|
||||||
db0ec473a016ce05c258cde18a217d47a9ea8324 assets/aphelion/models/item/dimension_changer.json
|
db0ec473a016ce05c258cde18a217d47a9ea8324 assets/aphelion/models/item/dimension_changer.json
|
||||||
279080c06ada87f54fd0a7b885b256dbe25a946a assets/aphelion/models/item/electric_arc_furnace.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
|
24cf60e70f7d9450b0e70cf017662e80971bae17 assets/aphelion/models/item/oxygen_test_block.json
|
||||||
74418ef1cf678e72e7534924274688ef5a68af0e assets/aphelion/models/item/test_block.json
|
74418ef1cf678e72e7534924274688ef5a68af0e assets/aphelion/models/item/test_block.json
|
||||||
88ca3602517e99f7feaed57eddfc96965a25761c assets/aphelion/models/item/vacuum_arc_furnace_controller.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.ModFluidTypes;
|
||||||
import net.xevianlight.aphelion.fluid.ModFluids;
|
import net.xevianlight.aphelion.fluid.ModFluids;
|
||||||
import net.xevianlight.aphelion.recipe.ModRecipes;
|
import net.xevianlight.aphelion.recipe.ModRecipes;
|
||||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceScreen;
|
import net.xevianlight.aphelion.screen.*;
|
||||||
import net.xevianlight.aphelion.screen.ModMenuTypes;
|
|
||||||
import net.xevianlight.aphelion.screen.TestBlockScreen;
|
|
||||||
import net.xevianlight.aphelion.screen.VacuumArcFurnaceScreen;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import net.xevianlight.aphelion.entites.vehicles.RocketRenderer;
|
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.TEST_BLOCK_MENU.get(), TestBlockScreen::new);
|
||||||
event.register(ModMenuTypes.ELECTRIC_ARC_FURNACE_MENU.get(), ElectricArcFurnaceScreen::new);
|
event.register(ModMenuTypes.ELECTRIC_ARC_FURNACE_MENU.get(), ElectricArcFurnaceScreen::new);
|
||||||
event.register(ModMenuTypes.VACUUM_ARC_FURNACE_MENU.get(), VacuumArcFurnaceScreen::new);
|
event.register(ModMenuTypes.VACUUM_ARC_FURNACE_MENU.get(), VacuumArcFurnaceScreen::new);
|
||||||
|
event.register(ModMenuTypes.GRAVITY_TEST_BLOCK_MENU.get(), GravityTestBlockScreen::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@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
|
// If in debug mode, renders a model made from the blocks
|
||||||
// that are currently returned by toBlockPositions(OxygenTestBlockEntity).
|
// that are currently returned by toBlockPositions(OxygenTestBlockEntity).
|
||||||
public void render(OxygenTestBlockEntity be, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {
|
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!
|
// This bit's debug only, folks!
|
||||||
if (!Minecraft.getInstance().gui.getDebugOverlay().showDebugScreen()) return;
|
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 net.xevianlight.aphelion.Aphelion;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
|
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
|
||||||
public final class OxygenDebugRender {
|
public final class OxygenDebugRender {
|
||||||
|
|
||||||
@@ -56,63 +58,9 @@ public final class OxygenDebugRender {
|
|||||||
MultiBufferSource.BufferSource bufferSource = mc.renderBuffers().bufferSource();
|
MultiBufferSource.BufferSource bufferSource = mc.renderBuffers().bufferSource();
|
||||||
VertexConsumer vc = bufferSource.getBuffer(OXYGEN_FILL);
|
VertexConsumer vc = bufferSource.getBuffer(OXYGEN_FILL);
|
||||||
|
|
||||||
// Render surface faces only (fast + pretty)
|
DebugRenderUtils.drawBlockArea(poseStack, vc, ClientOxygenCache.OXYGEN);
|
||||||
for (long l : ClientOxygenCache.OXYGEN) {
|
|
||||||
BlockPos p = BlockPos.of(l);
|
|
||||||
drawSurfaceFaces(poseStack, vc, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
bufferSource.endBatch(OXYGEN_FILL);
|
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(
|
BLOCK_ENTITIES.register("rocket_assembler_block_entity", () -> BlockEntityType.Builder.of(
|
||||||
RocketAssemblerBlockEntity::new, ModBlocks.ROCKET_ASSEMBLER_BLOCK.get()).build(null)
|
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.Aphelion;
|
||||||
import net.xevianlight.aphelion.block.custom.*;
|
import net.xevianlight.aphelion.block.custom.*;
|
||||||
import net.xevianlight.aphelion.block.dummy.VAFMultiblockDummyBlock;
|
import net.xevianlight.aphelion.block.dummy.VAFMultiblockDummyBlock;
|
||||||
|
import net.xevianlight.aphelion.block.entity.custom.GravityTestBlockEntity;
|
||||||
|
|
||||||
public class ModBlocks {
|
public class ModBlocks {
|
||||||
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(Aphelion.MOD_ID);
|
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> 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> 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> 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> 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> 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> 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> 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()));
|
// 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 {
|
public class GravitySavedData extends SavedData {
|
||||||
|
|
||||||
|
private Level level;
|
||||||
|
|
||||||
private final Long2IntOpenHashMap gravityData = new Long2IntOpenHashMap();
|
private final Long2IntOpenHashMap gravityData = new Long2IntOpenHashMap();
|
||||||
|
|
||||||
private static final String NAME = "aphelion_gravity";
|
private static final String NAME = "aphelion_gravity";
|
||||||
|
|
||||||
public static GravitySavedData create() {
|
public static GravitySavedData create(Level level) {
|
||||||
return new GravitySavedData();
|
return new GravitySavedData(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GravitySavedData(Level level) {
|
||||||
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -60,18 +66,18 @@ public class GravitySavedData extends SavedData {
|
|||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GravitySavedData load(CompoundTag tag, HolderLookup.Provider lookupProvider) {
|
public static GravitySavedData load(CompoundTag tag, HolderLookup.Provider lookupProvider, Level level) {
|
||||||
GravitySavedData data = create();
|
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");
|
long[] positions = tag.getLongArray("Position");
|
||||||
int[] values = tag.getIntArray("Value");
|
int[] values = tag.getIntArray("Value");
|
||||||
|
|
||||||
int length = Math.min(positions.length, values.length);
|
int length = Math.min(positions.length, values.length);
|
||||||
|
|
||||||
data.gravityData.ensureCapacity(length);
|
data.gravityData.ensureCapacity(length);
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
data.gravityData.put(positions[i], values[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;
|
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));
|
GravityData data = GravityData.unpack(gravityData.getOrDefault(center.asLong(), ABSENT));
|
||||||
return data.pack() == ABSENT ? null : data;
|
return data.pack() == ABSENT ? null : data;
|
||||||
}
|
}
|
||||||
@@ -94,6 +100,9 @@ public class GravitySavedData extends SavedData {
|
|||||||
gravityData.put(pos.asLong(), data.pack());
|
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
|
* Returns the strongest acceleration among all gravity regions that overlap this block position
|
||||||
*/
|
*/
|
||||||
public float getGravityMax (BlockPos pos) {
|
public float getGravityMax (BlockPos pos) {
|
||||||
float max = 0;
|
float max = -1;
|
||||||
|
|
||||||
List<GravityData> regions = getGravityRegions(pos);
|
List<GravityData> regions = getGravityRegions(pos);
|
||||||
|
|
||||||
@@ -124,6 +133,10 @@ public class GravitySavedData extends SavedData {
|
|||||||
if (accel > max) max = accel;
|
if (accel > max) max = accel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (max == -1) {
|
||||||
|
max = defaultGravity(this.level);
|
||||||
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +171,10 @@ public class GravitySavedData extends SavedData {
|
|||||||
|
|
||||||
public static GravitySavedData get(ServerLevel level) {
|
public static GravitySavedData get(ServerLevel level) {
|
||||||
return level.getDataStorage().computeIfAbsent(
|
return level.getDataStorage().computeIfAbsent(
|
||||||
new Factory<>(GravitySavedData::create, GravitySavedData::load),
|
new Factory<>(
|
||||||
|
() -> new GravitySavedData(level),
|
||||||
|
(tag, provider) -> GravitySavedData.load(tag, provider, level)
|
||||||
|
),
|
||||||
NAME
|
NAME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ public class GravityData {
|
|||||||
private float accel;
|
private float accel;
|
||||||
private float radius;
|
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 GRAVITY_PRECISION = 100.0f;
|
||||||
public static final float RADIUS_PRECISION = 100.0f;
|
public static final float RADIUS_PRECISION = 100.0f;
|
||||||
public static final float MAX_RADIUS = Short.MAX_VALUE / RADIUS_PRECISION;
|
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());
|
dropSelf(ModBlocks.OXYGEN_TEST_BLOCK.get());
|
||||||
dropOther(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get(), ItemStack.EMPTY.getItem());
|
dropOther(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get(), ItemStack.EMPTY.getItem());
|
||||||
dropSelf(ModBlocks.LAUNCH_PAD.get());
|
dropSelf(ModBlocks.LAUNCH_PAD.get());
|
||||||
|
dropSelf(ModBlocks.GRAVITY_TEST_BLOCK.get());
|
||||||
|
dropSelf(ModBlocks.ROCKET_ASSEMBLER_BLOCK.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ public class ModBlockStateProvider extends BlockStateProvider {
|
|||||||
// blockItem(ModBlocks.LAUNCH_PAD);
|
// blockItem(ModBlocks.LAUNCH_PAD);
|
||||||
|
|
||||||
blockItem(ModBlocks.ARC_FURNACE_CASING_BLOCK);
|
blockItem(ModBlocks.ARC_FURNACE_CASING_BLOCK);
|
||||||
|
|
||||||
blockWithItem(ModBlocks.OXYGEN_TEST_BLOCK);
|
blockWithItem(ModBlocks.OXYGEN_TEST_BLOCK);
|
||||||
|
blockWithItem(ModBlocks.GRAVITY_TEST_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void blockWithItem(DeferredBlock<?> deferredBlock) {
|
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.TestBlockEntity;
|
||||||
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
|
import net.xevianlight.aphelion.block.entity.custom.VacuumArcFurnaceControllerEntity;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||||
|
import net.xevianlight.aphelion.network.ClientPlayerStateUpdateHandler;
|
||||||
import net.xevianlight.aphelion.network.RocketPayloadHandlers;
|
import net.xevianlight.aphelion.network.RocketPayloadHandlers;
|
||||||
import net.xevianlight.aphelion.network.PartitionPayloadHandler;
|
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.PartitionPayload;
|
||||||
import net.xevianlight.aphelion.network.packet.RocketLaunchPayload;
|
import net.xevianlight.aphelion.network.packet.RocketLaunchPayload;
|
||||||
|
import net.xevianlight.aphelion.network.packet.UpdateGravityTestBlockPacket;
|
||||||
|
|
||||||
@EventBusSubscriber(modid = Aphelion.MOD_ID)
|
@EventBusSubscriber(modid = Aphelion.MOD_ID)
|
||||||
public class ModBusEvents {
|
public class ModBusEvents {
|
||||||
@@ -49,5 +53,16 @@ public class ModBusEvents {
|
|||||||
RocketPayloadHandlers::handleRocketLaunch
|
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.EntityType;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.level.Level;
|
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 net.xevianlight.aphelion.systems.OxygenService;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
@@ -26,4 +28,10 @@ public abstract class LivingEntityMixin extends Entity {
|
|||||||
OxygenService.entityTick(level, 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.client.Minecraft;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||||
|
import net.neoforged.neoforge.event.tick.ServerTickEvent;
|
||||||
import net.neoforged.neoforge.network.PacketDistributor;
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
import net.xevianlight.aphelion.Aphelion;
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
import net.xevianlight.aphelion.entites.vehicles.RocketEntity;
|
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.network.packet.RocketLaunchPayload;
|
||||||
|
|
||||||
import net.xevianlight.aphelion.client.AphelionClient;
|
import net.xevianlight.aphelion.client.AphelionClient;
|
||||||
@@ -27,4 +31,17 @@ public final class KeyNetwork {
|
|||||||
PacketDistributor.sendToServer(new RocketLaunchPayload(rocket.getId()));
|
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.neoforged.neoforge.registries.DeferredRegister;
|
||||||
import net.xevianlight.aphelion.Aphelion;
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
public class ModMenuTypes {
|
public class ModMenuTypes {
|
||||||
public static final DeferredRegister<MenuType<?>> MENUS =
|
public static final DeferredRegister<MenuType<?>> MENUS =
|
||||||
DeferredRegister.create(Registries.MENU, Aphelion.MOD_ID);
|
DeferredRegister.create(Registries.MENU, Aphelion.MOD_ID);
|
||||||
@@ -23,6 +25,9 @@ public class ModMenuTypes {
|
|||||||
public static DeferredHolder<MenuType<?>,MenuType<VacuumArcFurnaceMenu>> VACUUM_ARC_FURNACE_MENU =
|
public static DeferredHolder<MenuType<?>,MenuType<VacuumArcFurnaceMenu>> VACUUM_ARC_FURNACE_MENU =
|
||||||
registerMenuType("vacuum_arc_furnace_menu", VacuumArcFurnaceMenu::new);
|
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,
|
private static <T extends AbstractContainerMenu>DeferredHolder<MenuType<?>, MenuType<T>> registerMenuType(String name,
|
||||||
IContainerFactory<T> factory) {
|
IContainerFactory<T> factory) {
|
||||||
return MENUS.register(name, () -> IMenuTypeExtension.create(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",
|
"package": "net.xevianlight.aphelion.mixins",
|
||||||
"compatibilityLevel": "JAVA_21",
|
"compatibilityLevel": "JAVA_21",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"common.EntityMixin",
|
||||||
"common.LivingEntityMixin"
|
"common.LivingEntityMixin"
|
||||||
],
|
],
|
||||||
"client": [
|
"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",
|
"dimension": "minecraft:overworld",
|
||||||
"orbit_distance": 1,
|
"orbit_distance": 1,
|
||||||
"star_system": "aphelon:sol",
|
"star_system": "aphelon:sol",
|
||||||
"gravity": 1,
|
"gravity": 9.8,
|
||||||
"oxygen": false
|
"oxygen": false
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user