mirror of
https://github.com/XevianLight/Aphelion.git
synced 2026-05-11 10:00:54 +01:00
Compare commits
6 Commits
pipes-syst
...
gravity-sy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3154d32d79 | ||
|
|
aaa55b087f | ||
|
|
d9bd26e8a0 | ||
|
|
010fc7307f | ||
|
|
9356c43ea7 | ||
|
|
fa41966de4 |
@@ -1,11 +1,12 @@
|
|||||||
// 1.21.1 2026-02-04T21:03:31.3164337 Loot Tables
|
// 1.21.1 2026-02-06T10:36:07.5023829 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
|
||||||
|
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
|
afb6519a03415b8e0d5bafc9fadb70905a398046 data/aphelion/loot_table/blocks/oxygen_test_block.json
|
||||||
f3178154dadee30cc28f5ff23af45be98f2766cf data/aphelion/loot_table/blocks/rocket_assembler_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,21 +1,21 @@
|
|||||||
// 1.21.1 2026-02-04T21:03:31.3154339 Block States: aphelion
|
// 1.21.1 2026-02-06T10:36:07.5013847 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
|
||||||
85c7c0dab53d0219b315c822147a90ade9075844 assets/aphelion/blockstates/rocket_assembler_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
|
||||||
17eb7327e504f7a88028af804e046281d9719fdf assets/aphelion/models/block/rocket_assembler_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
|
||||||
dafa6e1a3cfd753e211ae94179a433c69e9d2a28 assets/aphelion/models/item/rocket_assembler_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"
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"parent": "aphelion:block/rocket_assembler_block"
|
|
||||||
}
|
|
||||||
@@ -11,11 +11,11 @@
|
|||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"type": "minecraft:item",
|
"type": "minecraft:item",
|
||||||
"name": "aphelion:rocket_assembler_block"
|
"name": "aphelion:gravity_test_block"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rolls": 1.0
|
"rolls": 1.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"random_sequence": "aphelion:blocks/rocket_assembler_block"
|
"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"
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@ import net.neoforged.neoforge.event.tick.ServerTickEvent;
|
|||||||
import net.neoforged.neoforge.network.PacketDistributor;
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
import net.xevianlight.aphelion.block.dummy.renderer.MultiblockDummyRenderer;
|
import net.xevianlight.aphelion.block.dummy.renderer.MultiblockDummyRenderer;
|
||||||
import net.xevianlight.aphelion.block.entity.custom.renderer.OxygenTestRenderer;
|
import net.xevianlight.aphelion.block.entity.custom.renderer.OxygenTestRenderer;
|
||||||
import net.xevianlight.aphelion.block.entity.custom.renderer.RocketAssemblerBlockEntityRenderer;
|
|
||||||
import net.xevianlight.aphelion.client.AphelionConfig;
|
import net.xevianlight.aphelion.client.AphelionConfig;
|
||||||
import net.xevianlight.aphelion.core.saveddata.EnvironmentSavedData;
|
import net.xevianlight.aphelion.core.saveddata.EnvironmentSavedData;
|
||||||
import net.xevianlight.aphelion.network.packet.PartitionPayload;
|
import net.xevianlight.aphelion.network.packet.PartitionPayload;
|
||||||
@@ -25,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;
|
||||||
|
|
||||||
@@ -140,7 +136,6 @@ public class Aphelion {
|
|||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void registerBER(EntityRenderersEvent.RegisterRenderers event) {
|
public static void registerBER(EntityRenderersEvent.RegisterRenderers event) {
|
||||||
event.registerBlockEntityRenderer(ModBlockEntities.VAF_MULTIBLOCK_DUMMY_ENTITY.get(), MultiblockDummyRenderer::new);
|
event.registerBlockEntityRenderer(ModBlockEntities.VAF_MULTIBLOCK_DUMMY_ENTITY.get(), MultiblockDummyRenderer::new);
|
||||||
event.registerBlockEntityRenderer(ModBlockEntities.ROCKET_ASSEMBLER_BLOCK_ENTITY.get(), RocketAssemblerBlockEntityRenderer::new);
|
|
||||||
// event.registerBlockEntityRenderer(ModBlockEntities.OXYGEN_TEST_BLOCK_ENTITY.get(), OxygenTestRenderer::new);
|
// event.registerBlockEntityRenderer(ModBlockEntities.OXYGEN_TEST_BLOCK_ENTITY.get(), OxygenTestRenderer::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,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
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|||||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||||
import net.xevianlight.aphelion.block.custom.base.BasicEntityBlock;
|
|
||||||
import net.xevianlight.aphelion.block.custom.base.BasicHorizontalEntityBlock;
|
|
||||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||||
@@ -36,14 +34,14 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ElectricArcFurnace extends BasicHorizontalEntityBlock {
|
public class ElectricArcFurnace extends BaseEntityBlock {
|
||||||
|
|
||||||
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||||
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
||||||
|
|
||||||
public ElectricArcFurnace(Properties properties) {
|
public ElectricArcFurnace(Properties properties) {
|
||||||
super(properties, true);
|
super(properties);
|
||||||
this.registerDefaultState(this.getStateDefinition().any()
|
this.registerDefaultState(this.getStateDefinition().any()
|
||||||
.setValue(FORMED, false));
|
.setValue(FORMED, false));
|
||||||
}
|
}
|
||||||
@@ -166,6 +164,25 @@ public class ElectricArcFurnace extends BasicHorizontalEntityBlock {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
||||||
|
if (level.isClientSide) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return createTickerHelper(blockEntityType, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), (level1, blockPos, blockState, electricArcFurnaceEntity) -> electricArcFurnaceEntity.tick(level1, blockPos, blockState));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||||
|
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||||
|
return state.rotate(mirror.getRotation(state.getValue(FACING)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
|
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false).setValue(FORMED, false);
|
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false).setValue(FORMED, false);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.block.custom;
|
|
||||||
|
|
||||||
import com.mojang.datafixers.kinds.Const;
|
|
||||||
import com.mojang.math.Constants;
|
|
||||||
import com.mojang.serialization.MapCodec;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
|
||||||
import net.minecraft.world.InteractionHand;
|
|
||||||
import net.minecraft.world.ItemInteractionResult;
|
|
||||||
import net.minecraft.world.entity.player.Player;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
|
||||||
import net.minecraft.world.level.BlockGetter;
|
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
|
||||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
|
||||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import net.minecraft.world.phys.shapes.BooleanOp;
|
|
||||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
|
||||||
import net.minecraft.world.phys.shapes.Shapes;
|
|
||||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
|
||||||
import net.xevianlight.aphelion.block.custom.base.BasicEntityBlock;
|
|
||||||
import net.xevianlight.aphelion.block.entity.custom.PipeTestBlockEntity;
|
|
||||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
// a lot of this is ai slop so take it with a grainlet of salt
|
|
||||||
public class PipeTestBlock extends BasicEntityBlock {
|
|
||||||
|
|
||||||
// shortcuts for each directional property because they're pretty verbose
|
|
||||||
// t/f here means is/isn't connected outgoing in that direction
|
|
||||||
public static final BooleanProperty NORTH = BlockStateProperties.NORTH;
|
|
||||||
public static final BooleanProperty SOUTH = BlockStateProperties.SOUTH;
|
|
||||||
public static final BooleanProperty EAST = BlockStateProperties.EAST;
|
|
||||||
public static final BooleanProperty WEST = BlockStateProperties.WEST;
|
|
||||||
public static final BooleanProperty UP = BlockStateProperties.UP;
|
|
||||||
public static final BooleanProperty DOWN = BlockStateProperties.DOWN;
|
|
||||||
|
|
||||||
// Voxel shape pieces to make the actual pipe model
|
|
||||||
private static final VoxelShape CORE = Block.box(6, 6, 6, 10, 10, 10);
|
|
||||||
private static final VoxelShape NORTH_SHAPE = Block.box(6, 6, 0, 10, 10, 6);
|
|
||||||
private static final VoxelShape SOUTH_SHAPE = Block.box(6, 6, 10, 10, 10, 16);
|
|
||||||
private static final VoxelShape EAST_SHAPE = Block.box(10, 6, 6, 16, 10, 10);
|
|
||||||
private static final VoxelShape WEST_SHAPE = Block.box(0, 6, 6, 6, 10, 10);
|
|
||||||
private static final VoxelShape UP_SHAPE = Block.box(6, 10, 6, 10, 16, 10);
|
|
||||||
private static final VoxelShape DOWN_SHAPE = Block.box(6, 0, 6, 10, 6, 10);
|
|
||||||
|
|
||||||
// Assembles the "VoxelShape" of the block which i assume is just the collision/place/mine hitbox
|
|
||||||
// later this should be cached for each different shape that we need
|
|
||||||
@Override
|
|
||||||
public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
|
|
||||||
VoxelShape shape = CORE;
|
|
||||||
|
|
||||||
if (state.getValue(NORTH)) shape = Shapes.join(shape, NORTH_SHAPE, BooleanOp.OR);
|
|
||||||
if (state.getValue(SOUTH)) shape = Shapes.join(shape, SOUTH_SHAPE, BooleanOp.OR);
|
|
||||||
if (state.getValue(EAST)) shape = Shapes.join(shape, EAST_SHAPE, BooleanOp.OR);
|
|
||||||
if (state.getValue(WEST)) shape = Shapes.join(shape, WEST_SHAPE, BooleanOp.OR);
|
|
||||||
if (state.getValue(UP)) shape = Shapes.join(shape, UP_SHAPE, BooleanOp.OR);
|
|
||||||
if (state.getValue(DOWN)) shape = Shapes.join(shape, DOWN_SHAPE, BooleanOp.OR);
|
|
||||||
|
|
||||||
return shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PipeTestBlock(Properties properties) {
|
|
||||||
super(properties, true);
|
|
||||||
this.registerDefaultState(this.stateDefinition.any()
|
|
||||||
.setValue(NORTH, false).setValue(SOUTH, false)
|
|
||||||
.setValue(EAST, false).setValue(WEST, false)
|
|
||||||
.setValue(UP, false).setValue(DOWN, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method determines the state; called when first placed
|
|
||||||
@Override
|
|
||||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
|
||||||
return makeConnections(context.getLevel(), context.getClickedPos());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the block; called when a neighbor changes
|
|
||||||
@Override
|
|
||||||
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos currentPos, BlockPos neighborPos) {
|
|
||||||
return makeConnections(level, currentPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Properties getProperties() {
|
|
||||||
return Properties.of().noOcclusion();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasAttachment(@Nullable PipeTestBlockEntity BE, Direction direction) {
|
|
||||||
return (BE != null && BE.hasAttachment(direction));
|
|
||||||
}
|
|
||||||
|
|
||||||
private BlockState makeConnections(LevelAccessor level, BlockPos pos) {
|
|
||||||
BlockEntity BE = level.getBlockEntity(pos);
|
|
||||||
PipeTestBlockEntity PTBE = null;
|
|
||||||
if (BE instanceof PipeTestBlockEntity found) {
|
|
||||||
PTBE = found;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.defaultBlockState()
|
|
||||||
.setValue(NORTH, canConnect(level, pos.north(), Direction.SOUTH) || hasAttachment(PTBE, Direction.NORTH))
|
|
||||||
.setValue(SOUTH, canConnect(level, pos.south(), Direction.NORTH) || hasAttachment(PTBE, Direction.SOUTH))
|
|
||||||
.setValue(EAST, canConnect(level, pos.east(), Direction.WEST) || hasAttachment(PTBE, Direction.EAST))
|
|
||||||
.setValue(WEST, canConnect(level, pos.west(), Direction.EAST) || hasAttachment(PTBE, Direction.WEST))
|
|
||||||
.setValue(UP, canConnect(level, pos.above(), Direction.DOWN) || hasAttachment(PTBE, Direction.UP))
|
|
||||||
.setValue(DOWN, canConnect(level, pos.below(), Direction.UP) || hasAttachment(PTBE, Direction.DOWN));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If a PipeTestBlock can connect to this position from the given direction.
|
|
||||||
/// If you're going to the NORTH of yourself, you should be accessing the SOUTH side.
|
|
||||||
public static boolean canConnect(LevelAccessor levelA, BlockPos neighborPos, Direction accessSide) {
|
|
||||||
// Methinks this is not the best way to test this.
|
|
||||||
boolean isPipe = levelA.getBlockState(neighborPos).is(ModBlocks.PIPE_TEST_BLOCK.get());
|
|
||||||
|
|
||||||
/// This code is AI, but I think it works? I think the reason it's a levelAccessor instead of a level
|
|
||||||
/// is that we're not sure if we're in, for example, an inventory slot or not.
|
|
||||||
/// Either way, this should only trigger when it makes sense (assuming this is correct in the first place)
|
|
||||||
boolean isInventory;
|
|
||||||
if (levelA instanceof Level level) {
|
|
||||||
isInventory = level.getCapability(Capabilities.ItemHandler.BLOCK, neighborPos, accessSide) != null;
|
|
||||||
} else {
|
|
||||||
isInventory = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isPipe || isInventory;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
|
|
||||||
BlockEntity BE = level.getBlockEntity(pos);
|
|
||||||
if (BE instanceof PipeTestBlockEntity pipe) {
|
|
||||||
// force everything connected to this pipe to reevaluate
|
|
||||||
if (pipe.graph != null) pipe.graph.invalidate();
|
|
||||||
}
|
|
||||||
super.onRemove(state, level, pos, newState, isMoving);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
|
||||||
builder.add(NORTH, SOUTH, EAST, WEST, UP, DOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult) {
|
|
||||||
|
|
||||||
BlockEntity BE = level.getBlockEntity(pos);
|
|
||||||
if (BE instanceof PipeTestBlockEntity PTBE) {
|
|
||||||
ItemInteractionResult r = PTBE.useItemOn(stack, state, level, pos, player, hand, hitResult, this);
|
|
||||||
|
|
||||||
BlockState newState = makeConnections(level, pos);
|
|
||||||
level.setBlock(pos, newState, 3);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
} else {
|
|
||||||
return super.useItemOn(stack, state, level, pos, player, hand, hitResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Doesn't block sunlight
|
|
||||||
// @Override
|
|
||||||
// public boolean propagatesSkylightDown(BlockState state, BlockGetter reader, BlockPos pos) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// This function doesn't do what the AI says it does. I have no idea what it actually does, though
|
|
||||||
// 2. Prevents the "black shadows" inside or around the pipe
|
|
||||||
// @Override
|
|
||||||
// public int getLightBlock(BlockState state, BlockGetter worldIn, BlockPos pos) {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// I don't know what this does, because Properties.noOcclusion() is the part that made the leaves keep
|
|
||||||
/// rendering their faces.
|
|
||||||
// 3. Tells adjacent blocks (like leaves) to keep rendering their faces
|
|
||||||
// @Override
|
|
||||||
// public boolean isOcclusionShapeFullBlock(BlockState state, BlockGetter worldIn, BlockPos pos) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// This bit affects how strong the ambient occlusion effect is
|
|
||||||
@Override
|
|
||||||
public float getShadeBrightness(BlockState state, BlockGetter world, BlockPos pos) {
|
|
||||||
return 1.0F; // Maintains full brightness
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
|
|
||||||
return new PipeTestBlockEntity(blockPos, blockState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,22 +2,21 @@ package net.xevianlight.aphelion.block.custom;
|
|||||||
|
|
||||||
import com.mojang.serialization.MapCodec;
|
import com.mojang.serialization.MapCodec;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.*;
|
import net.minecraft.world.level.block.*;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||||
import net.xevianlight.aphelion.block.custom.base.BasicHorizontalEntityBlock;
|
import net.xevianlight.aphelion.block.custom.base.BasicHorizontalEntityBlock;
|
||||||
import net.xevianlight.aphelion.block.entity.custom.RocketAssemblerBlockEntity;
|
import net.xevianlight.aphelion.block.entity.custom.RocketAssemblerBlockEntity;
|
||||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class RocketAssemblerBlock extends BasicHorizontalEntityBlock {
|
public class RocketAssemblerBlock extends BasicHorizontalEntityBlock {
|
||||||
|
|
||||||
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
|
||||||
|
|
||||||
public RocketAssemblerBlock(Properties properties) {
|
public RocketAssemblerBlock(Properties properties) {
|
||||||
super(properties, true);
|
super(properties, true);
|
||||||
}
|
}
|
||||||
@@ -25,7 +24,7 @@ public class RocketAssemblerBlock extends BasicHorizontalEntityBlock {
|
|||||||
public static final MapCodec<RocketAssemblerBlock> CODEC = simpleCodec(RocketAssemblerBlock::new);
|
public static final MapCodec<RocketAssemblerBlock> CODEC = simpleCodec(RocketAssemblerBlock::new);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull MapCodec<? extends BaseEntityBlock> codec() {
|
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||||
return CODEC;
|
return CODEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,18 +38,7 @@ public class RocketAssemblerBlock extends BasicHorizontalEntityBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
|
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||||
return new RocketAssemblerBlockEntity(blockPos, blockState);
|
return new RocketAssemblerBlockEntity(blockPos, blockState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
|
|
||||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(FORMED, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
|
||||||
builder.add(FORMED);
|
|
||||||
super.createBlockStateDefinition(builder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import net.minecraft.world.item.ItemStack;
|
|||||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
import net.minecraft.world.level.block.*;
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.SoundType;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||||
@@ -25,25 +25,25 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|||||||
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||||
import net.xevianlight.aphelion.block.custom.base.BasicHorizontalEntityBlock;
|
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
||||||
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.util.AphelionBlockStateProperties;
|
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||||
import net.xevianlight.aphelion.util.IMultiblockController;
|
import net.xevianlight.aphelion.util.IMultiblockController;
|
||||||
import net.xevianlight.aphelion.util.MultiblockHelper;
|
import net.xevianlight.aphelion.util.MultiblockHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {
|
public class VacuumArcFurnaceController extends BaseEntityBlock {
|
||||||
|
|
||||||
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
|
||||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||||
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
public static final BooleanProperty FORMED = AphelionBlockStateProperties.FORMED;
|
||||||
|
|
||||||
public VacuumArcFurnaceController(Properties properties) {
|
public VacuumArcFurnaceController(Properties properties) {
|
||||||
super(properties, true);
|
super(properties);
|
||||||
this.registerDefaultState(this.getStateDefinition().any()
|
this.registerDefaultState(this.getStateDefinition().any()
|
||||||
.setValue(FACING, Direction.NORTH)
|
.setValue(FACING, Direction.NORTH)
|
||||||
.setValue(LIT, false)
|
.setValue(LIT, false)
|
||||||
@@ -77,7 +77,7 @@ public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull InteractionResult useWithoutItem(@NotNull BlockState state, Level level, @NotNull BlockPos pos, @NotNull Player player, @NotNull BlockHitResult result) {
|
public InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult result) {
|
||||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
|
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
|
||||||
if (vacuumArcFurnaceEntity.isFormed())
|
if (vacuumArcFurnaceEntity.isFormed())
|
||||||
serverPlayer.openMenu(new SimpleMenuProvider(vacuumArcFurnaceEntity, Component.literal("Vacuum Arc Furnace")), pos);
|
serverPlayer.openMenu(new SimpleMenuProvider(vacuumArcFurnaceEntity, Component.literal("Vacuum Arc Furnace")), pos);
|
||||||
@@ -88,16 +88,21 @@ public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable BlockEntity newBlockEntity(@NotNull BlockPos blockPos, @NotNull BlockState blockState) {
|
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||||
return new VacuumArcFurnaceControllerEntity(blockPos, blockState);
|
return new VacuumArcFurnaceControllerEntity(blockPos, blockState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onRemove(BlockState state, Level level, @NotNull BlockPos pos, BlockState newState, boolean movedByPiston) {
|
public RenderShape getRenderShape(BlockState pState) {
|
||||||
|
return RenderShape.MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
||||||
if (!level.isClientSide && state.getBlock() != newState.getBlock()) {
|
if (!level.isClientSide && state.getBlock() != newState.getBlock()) {
|
||||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||||
if (blockEntity instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
|
if (blockEntity instanceof VacuumArcFurnaceControllerEntity vacuumArcFurnaceEntity) {
|
||||||
if(state.getValue(FORMED)) MultiblockHelper.unformForRemoval(level, state, pos, VacuumArcFurnaceControllerEntity.SHAPE, AphelionBlockStateProperties.FORMED);
|
if(state.getValue(FORMED)) MultiblockHelper.unformForRemoval(level, state, pos, vacuumArcFurnaceEntity.SHAPE, AphelionBlockStateProperties.FORMED);
|
||||||
vacuumArcFurnaceEntity.drops();
|
vacuumArcFurnaceEntity.drops();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +110,7 @@ public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPlace(BlockState state, Level level, @NotNull BlockPos pos, @NotNull BlockState oldState, boolean movedByPiston) {
|
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||||
super.onPlace(state, level, pos, oldState, movedByPiston);
|
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||||
if (!level.isClientSide() && oldState.getBlock() != state.getBlock()) {
|
if (!level.isClientSide() && oldState.getBlock() != state.getBlock()) {
|
||||||
BlockEntity blockEntity= level.getBlockEntity(pos);
|
BlockEntity blockEntity= level.getBlockEntity(pos);
|
||||||
@@ -115,7 +120,7 @@ public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getRedstoneSignalFromItemHandler(@Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
|
public static int getRedstoneSignalFromItemHandler(@javax.annotation.Nullable ItemStackHandler itemStackHandler, List<Integer> slots) {
|
||||||
if (itemStackHandler == null) {
|
if (itemStackHandler == null) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -136,22 +141,22 @@ public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSignalSource(@NotNull BlockState state) {
|
protected boolean isSignalSource(BlockState state) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getSignal(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull Direction direction) {
|
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
|
||||||
return super.getSignal(state, level, pos, direction);
|
return super.getSignal(state, level, pos, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasAnalogOutputSignal(@NotNull BlockState state) {
|
protected boolean hasAnalogOutputSignal(BlockState state) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getAnalogOutputSignal(@NotNull BlockState blockState, Level level, @NotNull BlockPos pos) {
|
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
|
||||||
List<Integer> slots = new ArrayList<>();
|
List<Integer> slots = new ArrayList<>();
|
||||||
slots.add(VacuumArcFurnaceControllerEntity.INPUT_SLOT);
|
slots.add(VacuumArcFurnaceControllerEntity.INPUT_SLOT);
|
||||||
slots.add(VacuumArcFurnaceControllerEntity.SECONDARY_INPUT_SLOT);
|
slots.add(VacuumArcFurnaceControllerEntity.SECONDARY_INPUT_SLOT);
|
||||||
@@ -164,6 +169,25 @@ public class VacuumArcFurnaceController extends BasicHorizontalEntityBlock {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
||||||
|
if (level.isClientSide) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return createTickerHelper(blockEntityType, ModBlockEntities.VACUUM_ARC_FURNACE_ENTITY.get(), (level1, blockPos, blockState, vacuumArcFurnaceEntity) -> vacuumArcFurnaceEntity.tick(level1, blockPos, blockState));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||||
|
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||||
|
return state.rotate(mirror.getRotation(state.getValue(FACING)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
|
public @Nullable BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false).setValue(FORMED, false);
|
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite()).setValue(LIT, false).setValue(FORMED, false);
|
||||||
|
|||||||
@@ -7,44 +7,16 @@ import net.minecraft.world.level.Level;
|
|||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
public interface TickableBlockEntity {
|
public interface TickableBlockEntity {
|
||||||
|
void tick(Level entityLevel, long time, BlockState blockState, BlockPos pos);
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs on both the client AND server.
|
|
||||||
* @param level
|
|
||||||
* @param time
|
|
||||||
* @param state
|
|
||||||
* @param pos
|
|
||||||
*/
|
|
||||||
default void tick (Level level, long time, BlockState state, BlockPos pos) {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs on the client only
|
|
||||||
* @param level
|
|
||||||
* @param time
|
|
||||||
* @param state
|
|
||||||
* @param pos
|
|
||||||
*/
|
|
||||||
void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos);
|
void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos);
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs on the server only
|
|
||||||
* @param level
|
|
||||||
* @param time
|
|
||||||
* @param state
|
|
||||||
* @param pos
|
|
||||||
*/
|
|
||||||
void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos);
|
void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos);
|
||||||
|
|
||||||
default boolean isInitialized() {
|
default boolean isInitialized() {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs on client AND server, once only.
|
|
||||||
* @param level
|
|
||||||
* @param state
|
|
||||||
* @param pos
|
|
||||||
*/
|
|
||||||
void firstTick(Level level, BlockState state, BlockPos pos);
|
void firstTick(Level level, BlockState state, BlockPos pos);
|
||||||
|
|
||||||
default void onRemoved() {}
|
default void onRemoved() {}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package net.xevianlight.aphelion.block.entity.custom;
|
package net.xevianlight.aphelion.block.entity.custom;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
@@ -9,7 +8,6 @@ import net.minecraft.network.chat.Component;
|
|||||||
import net.minecraft.network.protocol.Packet;
|
import net.minecraft.network.protocol.Packet;
|
||||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.Containers;
|
import net.minecraft.world.Containers;
|
||||||
import net.minecraft.world.MenuProvider;
|
import net.minecraft.world.MenuProvider;
|
||||||
import net.minecraft.world.SimpleContainer;
|
import net.minecraft.world.SimpleContainer;
|
||||||
@@ -27,7 +25,6 @@ import net.neoforged.neoforge.energy.IEnergyStorage;
|
|||||||
import net.neoforged.neoforge.items.IItemHandler;
|
import net.neoforged.neoforge.items.IItemHandler;
|
||||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||||
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
|
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
|
||||||
import net.xevianlight.aphelion.block.custom.base.TickableBlockEntity;
|
|
||||||
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
|
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
import net.xevianlight.aphelion.core.init.ModBlocks;
|
||||||
@@ -42,7 +39,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvider, TickableBlockEntity {
|
public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvider {
|
||||||
|
|
||||||
private final int SIZE = 4;
|
private final int SIZE = 4;
|
||||||
private int ENERGY_CAPACITY = 64000;
|
private int ENERGY_CAPACITY = 64000;
|
||||||
@@ -104,8 +101,10 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
|||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
public void tick(Level level, BlockPos pos, BlockState blockState) {
|
||||||
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
|
|
||||||
|
if (!blockState.getValue(AphelionBlockStateProperties.FORMED))
|
||||||
|
return;
|
||||||
|
|
||||||
chargeFromItem();
|
chargeFromItem();
|
||||||
|
|
||||||
@@ -115,8 +114,8 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
|||||||
// Recipe detected! We have enough energy to process
|
// Recipe detected! We have enough energy to process
|
||||||
progress++;
|
progress++;
|
||||||
useEnergy();
|
useEnergy();
|
||||||
level.setBlockAndUpdate(pos, state.setValue(ElectricArcFurnace.LIT, true));
|
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, true));
|
||||||
setChanged(level, pos, state);
|
setChanged(level, pos, blockState);
|
||||||
|
|
||||||
if (hasCraftingFinished()) {
|
if (hasCraftingFinished()) {
|
||||||
outputBlastingResult(INPUT_SLOT, OUTPUT_SLOT);
|
outputBlastingResult(INPUT_SLOT, OUTPUT_SLOT);
|
||||||
@@ -124,14 +123,14 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
|||||||
}
|
}
|
||||||
} else if (hasFurnaceRecipe(INPUT_SLOT) && !hasEnoughEnergyToCraft(MACHINE_ENERGY_COST)) {
|
} else if (hasFurnaceRecipe(INPUT_SLOT) && !hasEnoughEnergyToCraft(MACHINE_ENERGY_COST)) {
|
||||||
// Recipe detected but we ran out of power
|
// Recipe detected but we ran out of power
|
||||||
level.setBlockAndUpdate(pos, state.setValue(ElectricArcFurnace.LIT, false));
|
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, state);
|
setChanged(level, pos, blockState);
|
||||||
progress = progress > 0 ? progress - 1 : 0;
|
progress = progress > 0 ? progress - 1 : 0;
|
||||||
} else {
|
} else {
|
||||||
// Invalid recipe
|
// Invalid recipe
|
||||||
resetProgress();
|
resetProgress();
|
||||||
level.setBlockAndUpdate(pos, state.setValue(ElectricArcFurnace.LIT, false));
|
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, state);
|
setChanged(level, pos, blockState);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Secondary slot is NOT empty, try alloying recipes
|
// Secondary slot is NOT empty, try alloying recipes
|
||||||
@@ -140,8 +139,8 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
|||||||
// Alloy recipe detected! We have enough energy to process
|
// Alloy recipe detected! We have enough energy to process
|
||||||
progress++;
|
progress++;
|
||||||
useEnergy();
|
useEnergy();
|
||||||
level.setBlockAndUpdate(pos, state.setValue(ElectricArcFurnace.LIT, true));
|
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, true));
|
||||||
setChanged(level, pos, state);
|
setChanged(level, pos, blockState);
|
||||||
|
|
||||||
if (hasCraftingFinished()) {
|
if (hasCraftingFinished()) {
|
||||||
outputAlloyingResult(INPUT_SLOT, SECONDARY_INPUT_SLOT, OUTPUT_SLOT);
|
outputAlloyingResult(INPUT_SLOT, SECONDARY_INPUT_SLOT, OUTPUT_SLOT);
|
||||||
@@ -149,17 +148,19 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Recipe detected but we ran out of power
|
// Recipe detected but we ran out of power
|
||||||
level.setBlockAndUpdate(pos, state.setValue(ElectricArcFurnace.LIT, false));
|
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, state);
|
setChanged(level, pos, blockState);
|
||||||
progress = progress > 0 ? progress - 1 : 0;
|
progress = progress > 0 ? progress - 1 : 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Invalid recipe
|
// Invalid recipe
|
||||||
resetProgress();
|
resetProgress();
|
||||||
level.setBlockAndUpdate(pos, state.setValue(ElectricArcFurnace.LIT, false));
|
level.setBlockAndUpdate(pos, blockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, state);
|
setChanged(level, pos, blockState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void chargeFromItem() {
|
private void chargeFromItem() {
|
||||||
@@ -407,14 +408,4 @@ public class ElectricArcFurnaceEntity extends BlockEntity implements MenuProvide
|
|||||||
new MultiblockHelper.ShapePart(new BlockPos(3,0,3), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
new MultiblockHelper.ShapePart(new BlockPos(3,0,3), s -> s.is(ModBlocks.ARC_FURNACE_CASING_BLOCK)),
|
||||||
// new MultiblockHelper.ShapePart(new BlockPos(-1,0,0), s -> s.is(Blocks.AMETHYST_BLOCK))
|
// new MultiblockHelper.ShapePart(new BlockPos(-1,0,0), s -> s.is(Blocks.AMETHYST_BLOCK))
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void firstTick(Level level, BlockState state, BlockPos pos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.block.entity.custom;
|
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.InteractionHand;
|
|
||||||
import net.minecraft.world.ItemInteractionResult;
|
|
||||||
import net.minecraft.world.entity.player.Player;
|
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
|
||||||
import net.xevianlight.aphelion.Aphelion;
|
|
||||||
import net.xevianlight.aphelion.block.custom.PipeTestBlock;
|
|
||||||
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.systems.conveyor.*;
|
|
||||||
import net.xevianlight.aphelion.util.FloodFill3D;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class PipeTestBlockEntity extends BlockEntity implements TickableBlockEntity {
|
|
||||||
public @Nullable ConveyorNetwork graph = null;
|
|
||||||
public final Map<Direction, @Nullable ConveyorAttachment> attachments = new HashMap<>();
|
|
||||||
public final Map<Direction, @Nullable ConveyorOutput> outputs = new HashMap<>();
|
|
||||||
|
|
||||||
public PipeTestBlockEntity(BlockPos pos, BlockState blockState) {
|
|
||||||
super(ModBlockEntities.PIPE_TEST_BLOCK_ENTITY.get(), pos, blockState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
|
|
||||||
if (this.graph == null) initGraph(level, pos);
|
|
||||||
// TODO: Call this as little as necessary
|
|
||||||
makeOutputs(level, state, pos);
|
|
||||||
|
|
||||||
for (Direction dir : Direction.values()) {
|
|
||||||
ConveyorAttachment attachment = attachments.get(dir);
|
|
||||||
if (attachment != null) {
|
|
||||||
attachment.tick(level, state, pos, dir, graph);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void firstTick(Level level, BlockState state, BlockPos pos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addOutput(Direction dir, ConveyorOutput output) {
|
|
||||||
outputs.put(dir, output);
|
|
||||||
if (graph != null) graph.outputs.add(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOutput(Direction dir) {
|
|
||||||
ConveyorOutput old = outputs.get(dir);
|
|
||||||
if (graph != null) graph.outputs.remove(old);
|
|
||||||
outputs.remove(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canOutputTo(Level level, BlockPos pos, Direction accessSide) {
|
|
||||||
return level.getCapability(Capabilities.ItemHandler.BLOCK, pos, accessSide) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void makeOutputs(ServerLevel level, BlockState state, BlockPos pos) {
|
|
||||||
BlockPos.MutableBlockPos neighbor = new BlockPos.MutableBlockPos();
|
|
||||||
for (Direction dir : Direction.values()) {
|
|
||||||
neighbor.setWithOffset(pos, dir);
|
|
||||||
|
|
||||||
if (canOutputTo(level, neighbor, dir.getOpposite()) && attachments.get(dir) == null && outputs.get(dir) == null) {
|
|
||||||
addOutput(dir, new BasicItemOutput(level, pos, dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(canOutputTo(level, neighbor, dir.getOpposite()) && attachments.get(dir) == null) && outputs.get(dir) != null) {
|
|
||||||
removeOutput(dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasAttachment(Direction direction) {
|
|
||||||
return attachments.get(direction) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simplest implementation I can think of
|
|
||||||
public static void initGraph(Level level, BlockPos pos) {
|
|
||||||
Aphelion.LOGGER.info("Init graph from {}", pos);
|
|
||||||
if (!level.getBlockState(pos).is(ModBlocks.PIPE_TEST_BLOCK.get())) return;
|
|
||||||
Set<BlockPos> pipes = FloodFill3D.run(
|
|
||||||
level, pos, 1000,
|
|
||||||
(var v1, var v2, var state, var v4, var v5, var v6) -> state.is(ModBlocks.PIPE_TEST_BLOCK.get()),
|
|
||||||
false);
|
|
||||||
|
|
||||||
Aphelion.LOGGER.info("Got {} pipes", pipes.size());
|
|
||||||
ConveyorNetwork graph = new ConveyorNetwork();
|
|
||||||
for (BlockPos pipePos : pipes) {
|
|
||||||
BlockEntity BE = level.getBlockEntity(pipePos);
|
|
||||||
if (BE instanceof PipeTestBlockEntity pipe) {
|
|
||||||
// Invalidate any old graphs
|
|
||||||
if (pipe.graph != null) {
|
|
||||||
pipe.graph.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.addPipe(pipe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAttachment(Direction side, ConveyorAttachment attachment) {
|
|
||||||
attachments.put(side, attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean trySetAttachment(Direction side, ConveyorAttachment attachment) {
|
|
||||||
if (hasAttachment(side)) return false;
|
|
||||||
setAttachment(side, attachment);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isAttachmentItem(ItemStack stack) {
|
|
||||||
//TODO: add actual attachment items instead of just stone
|
|
||||||
return stack.is(Item.byId(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server only
|
|
||||||
public ConveyorAttachment getAttachmentForItem(ItemStack stack, Direction side) {
|
|
||||||
if (level.isClientSide()) throw new RuntimeException("Cannot get attachment item on client side!");
|
|
||||||
return new BasicItemExtractAttachment((ServerLevel) level, getBlockPos(), side);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called from pipe test block's useItemOn
|
|
||||||
public ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult, PipeTestBlock block) {
|
|
||||||
if (level.isClientSide) return ItemInteractionResult.SUCCESS;
|
|
||||||
Vec3 relativePos = hitResult.getLocation().subtract(pos.getCenter());
|
|
||||||
Direction pipeSide = Direction.getNearest(relativePos);
|
|
||||||
|
|
||||||
if (isAttachmentItem(stack)) {
|
|
||||||
boolean success = trySetAttachment(pipeSide, getAttachmentForItem(stack, pipeSide));
|
|
||||||
|
|
||||||
return success ? ItemInteractionResult.SUCCESS : ItemInteractionResult.FAIL;
|
|
||||||
} else {
|
|
||||||
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; // goes through with whatever other interaction (placing a block, etc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +1,19 @@
|
|||||||
package net.xevianlight.aphelion.block.entity.custom;
|
package net.xevianlight.aphelion.block.entity.custom;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.network.Connection;
|
|
||||||
import net.minecraft.network.protocol.Packet;
|
|
||||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
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.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
||||||
import net.xevianlight.aphelion.Aphelion;
|
|
||||||
import net.xevianlight.aphelion.block.custom.base.TickableBlockEntity;
|
import net.xevianlight.aphelion.block.custom.base.TickableBlockEntity;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
|
||||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
|
||||||
import net.xevianlight.aphelion.util.ModTags;
|
|
||||||
import net.xevianlight.aphelion.util.RocketStructure;
|
import net.xevianlight.aphelion.util.RocketStructure;
|
||||||
import org.apache.commons.lang3.NotImplementedException;
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
|
|
||||||
public class RocketAssemblerBlockEntity extends BlockEntity implements TickableBlockEntity {
|
public class RocketAssemblerBlockEntity extends BlockEntity implements TickableBlockEntity {
|
||||||
|
|
||||||
Direction facing;
|
|
||||||
BlockPos padScanStart = BlockPos.ZERO;
|
|
||||||
private PadInfo padBounds;
|
|
||||||
|
|
||||||
public @Nullable PadInfo getPadBounds() {
|
|
||||||
return padBounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInitialized;
|
public boolean isInitialized;
|
||||||
@Override
|
@Override
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
@@ -49,156 +24,13 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB
|
|||||||
super(ModBlockEntities.ROCKET_ASSEMBLER_BLOCK_ENTITY.get(), pos, blockState);
|
super(ModBlockEntities.ROCKET_ASSEMBLER_BLOCK_ENTITY.get(), pos, blockState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record PadInfo(BlockPos min, BlockPos max) {
|
public void tick(Level level1, BlockPos blockPos, BlockState blockState) {
|
||||||
public int getVolume() {
|
|
||||||
int dx = max.getX() - min.getX() + 1;
|
|
||||||
int dy = max.getY() - min.getY() + 1;
|
|
||||||
int dz = max.getZ() - min.getZ() + 1;
|
|
||||||
|
|
||||||
return dx * dy * dz;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Block TOWER_BLOCK = ModBlocks.BLOCK_STEEL.get();
|
public boolean getPlatform() {
|
||||||
public BlockPos towerBasePos;
|
|
||||||
|
|
||||||
public @Nullable PadInfo getPlatform() {
|
|
||||||
// TODO
|
// TODO
|
||||||
int y = this.padScanStart.getY();
|
throw new NotImplementedException();
|
||||||
BlockPos start = this.padScanStart;
|
|
||||||
|
|
||||||
if (level == null) return null;
|
|
||||||
if (!isPad(level.getBlockState(start))) return null;
|
|
||||||
|
|
||||||
int minX = start.getX();
|
|
||||||
while (isPad(level.getBlockState(new BlockPos(minX - 1, y, start.getZ())))) minX--;
|
|
||||||
|
|
||||||
// Find maxX by walking east
|
|
||||||
int maxX = start.getX();
|
|
||||||
while (isPad(level.getBlockState(new BlockPos(maxX + 1, y, start.getZ())))) maxX++;
|
|
||||||
|
|
||||||
// Find minZ by walking north
|
|
||||||
int minZ = start.getZ();
|
|
||||||
while (isPad(level.getBlockState(new BlockPos(start.getX(), y, minZ - 1)))) minZ--;
|
|
||||||
|
|
||||||
// Find maxZ by walking south
|
|
||||||
int maxZ = start.getZ();
|
|
||||||
while (isPad(level.getBlockState(new BlockPos(start.getX(), y, maxZ + 1)))) maxZ++;
|
|
||||||
|
|
||||||
int width = (maxX - minX) + 1;
|
|
||||||
int length = (maxZ - minZ) + 1;
|
|
||||||
|
|
||||||
// Must be square
|
|
||||||
if (width != length) return null;
|
|
||||||
|
|
||||||
// Verify the entire rectangle is filled with pad blocks
|
|
||||||
for (int x = minX; x <= maxX; x++) {
|
|
||||||
for (int z = minZ; z <= maxZ; z++) {
|
|
||||||
if (!isPad(level.getBlockState(new BlockPos(x, y, z)))) return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PadInfo(new BlockPos(minX, y, minZ), new BlockPos(maxX, y, maxZ));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean connected(BlockState state, Direction dir) {
|
|
||||||
return switch (dir) {
|
|
||||||
case NORTH -> state.getValue(BlockStateProperties.NORTH);
|
|
||||||
case SOUTH -> state.getValue(BlockStateProperties.SOUTH);
|
|
||||||
case EAST -> state.getValue(BlockStateProperties.EAST);
|
|
||||||
case WEST -> state.getValue(BlockStateProperties.WEST);
|
|
||||||
default -> false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable PadInfo getPlatformFill() {
|
|
||||||
if (level == null) return null;
|
|
||||||
|
|
||||||
BlockPos start = this.padScanStart;
|
|
||||||
if (!isPad(level.getBlockState(start))) return null;
|
|
||||||
|
|
||||||
|
|
||||||
final int y = start.getY();
|
|
||||||
int towerHeight = 0;
|
|
||||||
|
|
||||||
ArrayDeque<BlockPos> queue = new ArrayDeque<>();
|
|
||||||
LongOpenHashSet visited = new LongOpenHashSet();
|
|
||||||
|
|
||||||
queue.add(start);
|
|
||||||
visited.add(start.asLong());
|
|
||||||
|
|
||||||
final Direction[] CARDINALS = {Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST};
|
|
||||||
// When the $#$# are we going to have a rocket larger than 64x64... don't...
|
|
||||||
final int MAX_PAD_BLOCKS = 4096;
|
|
||||||
|
|
||||||
boolean towerFound = false;
|
|
||||||
while (!queue.isEmpty()) {
|
|
||||||
BlockPos p = queue.removeFirst();
|
|
||||||
BlockState s = level.getBlockState(p);
|
|
||||||
|
|
||||||
// We trust block states entirely. If a block state says it has a pad in a direction and is wrong, something else has failed. To minimize level checks and have this run as fast as possible, I won't compare the block
|
|
||||||
// if (!isPad(s)) continue;
|
|
||||||
|
|
||||||
for (Direction d : CARDINALS) {
|
|
||||||
// Only keep going if the block claims to have a neighbor in that direction
|
|
||||||
BlockPos n = p.relative(d);
|
|
||||||
|
|
||||||
if (!connected(s, d)) {
|
|
||||||
if (level.getBlockState(n).is(TOWER_BLOCK)) {
|
|
||||||
if (!towerFound) {
|
|
||||||
towerBasePos = n;
|
|
||||||
towerFound = true;
|
|
||||||
} else if (!n.equals(towerBasePos)) {
|
|
||||||
Aphelion.LOGGER.warn("Multiple towers found, rocket pad invalid");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visited.contains(n.asLong())) continue; // skip if we've already seen this block
|
|
||||||
|
|
||||||
visited.add(n.asLong());
|
|
||||||
queue.addLast(n);
|
|
||||||
|
|
||||||
if (visited.size() > MAX_PAD_BLOCKS) return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pads missing a tower should be invalid
|
|
||||||
if (!towerFound || towerBasePos == null) return null;
|
|
||||||
towerHeight = getTowerHeight(level, towerBasePos);
|
|
||||||
if (towerHeight <= 0) return null;
|
|
||||||
|
|
||||||
int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
|
|
||||||
int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
|
|
||||||
|
|
||||||
for (Long p : visited) {
|
|
||||||
minX = Math.min(minX, BlockPos.of(p).getX());
|
|
||||||
maxX = Math.max(maxX, BlockPos.of(p).getX());
|
|
||||||
minZ = Math.min(minZ, BlockPos.of(p).getZ());
|
|
||||||
maxZ = Math.max(maxZ, BlockPos.of(p).getZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = (maxX - minX) + 1;
|
|
||||||
int length = (maxZ - minZ) + 1;
|
|
||||||
|
|
||||||
// SQUARE AND SOLID??? The math works out here that this will only be true if the number of blocks found matches the side lengths squared. We don't need to check for holes manually!
|
|
||||||
if (visited.size() != length * width || length != width) return null;
|
|
||||||
|
|
||||||
return new PadInfo(new BlockPos(minX, y + 1, minZ), new BlockPos(maxX, y + towerHeight, maxZ));
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTowerHeight(@NotNull Level level, @NotNull BlockPos base) {
|
|
||||||
int h = 0;
|
|
||||||
BlockPos p = base.above();
|
|
||||||
|
|
||||||
while (level.getBlockState(p).is(TOWER_BLOCK)) {
|
|
||||||
h++;
|
|
||||||
p = p.above();
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RocketStructure scan() {
|
public RocketStructure scan() {
|
||||||
@@ -206,6 +38,11 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(Level entityLevel, long time, BlockState blockState, BlockPos pos) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos) {
|
public void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos) {
|
||||||
|
|
||||||
@@ -213,87 +50,11 @@ public class RocketAssemblerBlockEntity extends BlockEntity implements TickableB
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
|
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
|
||||||
PadInfo newBounds = getPlatformFill();
|
|
||||||
setPadBoundsAndSync(newBounds);
|
|
||||||
|
|
||||||
boolean formed = newBounds != null;
|
|
||||||
if (state.getValue(AphelionBlockStateProperties.FORMED) != formed) {
|
|
||||||
level.setBlockAndUpdate(pos, state.setValue(AphelionBlockStateProperties.FORMED, formed));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void firstTick(Level level, BlockState state, BlockPos pos) {
|
public void firstTick(Level level, BlockState state, BlockPos pos) {
|
||||||
facing = getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING);
|
|
||||||
padScanStart = getBlockPos().mutable().below().relative(facing.getOpposite());
|
|
||||||
this.isInitialized = true;
|
this.isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean isPad(BlockState s) {
|
|
||||||
return s.is(ModTags.Blocks.LAUNCH_PAD); // or s.getBlock() == ModBlocks.PAD.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
|
||||||
super.saveAdditional(tag, registries);
|
|
||||||
|
|
||||||
PadInfo pad = this.padBounds;
|
|
||||||
if (pad != null) {
|
|
||||||
tag.putLong("PadMin", padBounds.min().asLong());
|
|
||||||
tag.putLong("PadMax", padBounds.max().asLong());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void loadAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
|
||||||
super.loadAdditional(tag, registries);
|
|
||||||
|
|
||||||
if (tag.contains("PadMin") && tag.contains("PadMax")) {
|
|
||||||
BlockPos min = BlockPos.of(tag.getLong("PadMin"));
|
|
||||||
BlockPos max = BlockPos.of(tag.getLong("PadMax"));
|
|
||||||
this.padBounds = new PadInfo(min, max);
|
|
||||||
} else {
|
|
||||||
this.padBounds = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull CompoundTag getUpdateTag(HolderLookup.@NotNull Provider registries) {
|
|
||||||
CompoundTag tag = super.getUpdateTag(registries);
|
|
||||||
saveAdditional(tag, registries);
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleUpdateTag(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) {
|
|
||||||
loadAdditional(tag, registries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPadBoundsAndSync(@Nullable PadInfo newBounds) {
|
|
||||||
if (java.util.Objects.equals(this.padBounds, newBounds)) return;
|
|
||||||
|
|
||||||
this.padBounds = newBounds;
|
|
||||||
setChanged(); // marks BE dirty for saving
|
|
||||||
|
|
||||||
if (level instanceof ServerLevel server) {
|
|
||||||
BlockState state = getBlockState();
|
|
||||||
server.sendBlockUpdated(worldPosition, state, state, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Packet<ClientGamePacketListener> getUpdatePacket() {
|
|
||||||
// sends the tag from getUpdateTag()
|
|
||||||
return ClientboundBlockEntityDataPacket.create(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDataPacket(@NotNull Connection net, ClientboundBlockEntityDataPacket pkt, HolderLookup.@NotNull Provider registries) {
|
|
||||||
// apply the received tag on client
|
|
||||||
CompoundTag tag = pkt.getTag();
|
|
||||||
if (tag != null) {
|
|
||||||
this.loadAdditional(tag, registries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package net.xevianlight.aphelion.block.entity.custom;
|
package net.xevianlight.aphelion.block.entity.custom;
|
||||||
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
@@ -9,7 +8,6 @@ import net.minecraft.network.chat.Component;
|
|||||||
import net.minecraft.network.protocol.Packet;
|
import net.minecraft.network.protocol.Packet;
|
||||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.Containers;
|
import net.minecraft.world.Containers;
|
||||||
import net.minecraft.world.MenuProvider;
|
import net.minecraft.world.MenuProvider;
|
||||||
import net.minecraft.world.SimpleContainer;
|
import net.minecraft.world.SimpleContainer;
|
||||||
@@ -30,14 +28,14 @@ import net.neoforged.neoforge.capabilities.Capabilities;
|
|||||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||||
import net.neoforged.neoforge.items.IItemHandler;
|
import net.neoforged.neoforge.items.IItemHandler;
|
||||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||||
import net.xevianlight.aphelion.block.custom.VacuumArcFurnaceController;
|
import net.xevianlight.aphelion.block.custom.ElectricArcFurnace;
|
||||||
import net.xevianlight.aphelion.block.custom.base.TickableBlockEntity;
|
|
||||||
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
|
import net.xevianlight.aphelion.block.entity.energy.ModEnergyStorage;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
import net.xevianlight.aphelion.core.init.ModBlocks;
|
||||||
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipe;
|
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipe;
|
||||||
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipeInput;
|
import net.xevianlight.aphelion.recipe.ElectricArcFurnaceRecipeInput;
|
||||||
import net.xevianlight.aphelion.recipe.ModRecipes;
|
import net.xevianlight.aphelion.recipe.ModRecipes;
|
||||||
|
import net.xevianlight.aphelion.screen.VacuumArcFurnaceMenu;
|
||||||
import net.xevianlight.aphelion.screen.ElectricArcFurnaceMenu;
|
import net.xevianlight.aphelion.screen.ElectricArcFurnaceMenu;
|
||||||
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
import net.xevianlight.aphelion.util.AphelionBlockStateProperties;
|
||||||
import net.xevianlight.aphelion.util.IMultiblockController;
|
import net.xevianlight.aphelion.util.IMultiblockController;
|
||||||
@@ -47,16 +45,16 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class VacuumArcFurnaceControllerEntity extends BlockEntity implements MenuProvider, IMultiblockController, TickableBlockEntity {
|
public class VacuumArcFurnaceControllerEntity extends BlockEntity implements MenuProvider, IMultiblockController {
|
||||||
|
|
||||||
private final int SIZE = 4;
|
private final int SIZE = 4;
|
||||||
private final int ENERGY_CAPACITY = 64000;
|
private int ENERGY_CAPACITY = 64000;
|
||||||
private final int MAX_TRANSFER = 320;
|
private int MAX_TRANSFER = 320;
|
||||||
private int progress = 0;
|
private int progress = 0;
|
||||||
private int maxProgress = 100;
|
private int maxProgress = 100;
|
||||||
private final int DEFAULT_MAX_PROGRESS = 100;
|
private final int DEFAULT_MAX_PROGRESS = 100;
|
||||||
private final ContainerData data;
|
private final ContainerData data;
|
||||||
private final int MACHINE_ENERGY_COST = 20;
|
private int MACHINE_ENERGY_COST = 20;
|
||||||
|
|
||||||
public static final int INPUT_SLOT = 0;
|
public static final int INPUT_SLOT = 0;
|
||||||
public static final int SECONDARY_INPUT_SLOT = 1;
|
public static final int SECONDARY_INPUT_SLOT = 1;
|
||||||
@@ -101,7 +99,7 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
@Override
|
@Override
|
||||||
protected void onContentsChanged(int slot) {
|
protected void onContentsChanged(int slot) {
|
||||||
setChanged();
|
setChanged();
|
||||||
if (level != null && !level.isClientSide()) {
|
if(!level.isClientSide()) {
|
||||||
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,8 +114,7 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
public void tick(Level level, BlockPos pos, BlockState blockState) {
|
||||||
public void serverTick(ServerLevel level, long time, BlockState state, BlockPos pos) {
|
|
||||||
|
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
dirty = false;
|
dirty = false;
|
||||||
@@ -127,7 +124,7 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
|
|
||||||
BlockState newBlockState = level.getBlockState(pos);
|
BlockState newBlockState = level.getBlockState(pos);
|
||||||
|
|
||||||
if (!state.getValue(AphelionBlockStateProperties.FORMED))
|
if (!blockState.getValue(AphelionBlockStateProperties.FORMED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
chargeFromItem();
|
chargeFromItem();
|
||||||
@@ -138,7 +135,7 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
// Recipe detected! We have enough energy to process
|
// Recipe detected! We have enough energy to process
|
||||||
progress++;
|
progress++;
|
||||||
useEnergy();
|
useEnergy();
|
||||||
level.setBlockAndUpdate(pos, newBlockState.setValue(VacuumArcFurnaceController.LIT, true));
|
level.setBlockAndUpdate(pos, newBlockState.setValue(ElectricArcFurnace.LIT, true));
|
||||||
setChanged(level, pos, newBlockState);
|
setChanged(level, pos, newBlockState);
|
||||||
|
|
||||||
if (hasCraftingFinished()) {
|
if (hasCraftingFinished()) {
|
||||||
@@ -147,13 +144,13 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
}
|
}
|
||||||
} else if (hasFurnaceRecipe(INPUT_SLOT) && !hasEnoughEnergyToCraft(MACHINE_ENERGY_COST)) {
|
} else if (hasFurnaceRecipe(INPUT_SLOT) && !hasEnoughEnergyToCraft(MACHINE_ENERGY_COST)) {
|
||||||
// Recipe detected but we ran out of power
|
// Recipe detected but we ran out of power
|
||||||
level.setBlockAndUpdate(pos, newBlockState.setValue(VacuumArcFurnaceController.LIT, false));
|
level.setBlockAndUpdate(pos, newBlockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, newBlockState);
|
setChanged(level, pos, newBlockState);
|
||||||
progress = progress > 0 ? progress - 1 : 0;
|
progress = progress > 0 ? progress - 1 : 0;
|
||||||
} else {
|
} else {
|
||||||
// Invalid recipe
|
// Invalid recipe
|
||||||
resetProgress();
|
resetProgress();
|
||||||
level.setBlockAndUpdate(pos, newBlockState.setValue(VacuumArcFurnaceController.LIT, false));
|
level.setBlockAndUpdate(pos, newBlockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, newBlockState);
|
setChanged(level, pos, newBlockState);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -163,7 +160,7 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
// Alloy recipe detected! We have enough energy to process
|
// Alloy recipe detected! We have enough energy to process
|
||||||
progress++;
|
progress++;
|
||||||
useEnergy();
|
useEnergy();
|
||||||
level.setBlockAndUpdate(pos, newBlockState.setValue(VacuumArcFurnaceController.LIT, true));
|
level.setBlockAndUpdate(pos, newBlockState.setValue(ElectricArcFurnace.LIT, true));
|
||||||
setChanged(level, pos, newBlockState);
|
setChanged(level, pos, newBlockState);
|
||||||
|
|
||||||
if (hasCraftingFinished()) {
|
if (hasCraftingFinished()) {
|
||||||
@@ -172,14 +169,14 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Recipe detected but we ran out of power
|
// Recipe detected but we ran out of power
|
||||||
level.setBlockAndUpdate(pos, newBlockState.setValue(VacuumArcFurnaceController.LIT, false));
|
level.setBlockAndUpdate(pos, newBlockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, newBlockState);
|
setChanged(level, pos, newBlockState);
|
||||||
progress = progress > 0 ? progress - 1 : 0;
|
progress = progress > 0 ? progress - 1 : 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Invalid recipe
|
// Invalid recipe
|
||||||
resetProgress();
|
resetProgress();
|
||||||
level.setBlockAndUpdate(pos, newBlockState.setValue(VacuumArcFurnaceController.LIT, false));
|
level.setBlockAndUpdate(pos, newBlockState.setValue(ElectricArcFurnace.LIT, false));
|
||||||
setChanged(level, pos, newBlockState);
|
setChanged(level, pos, newBlockState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -414,7 +411,7 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
@Override
|
@Override
|
||||||
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
|
||||||
if (isFormed())
|
if (isFormed())
|
||||||
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
|
return new VacuumArcFurnaceMenu(i, inventory, this, this.data);
|
||||||
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
|
return new ElectricArcFurnaceMenu(i, inventory, this, this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,14 +527,4 @@ public class VacuumArcFurnaceControllerEntity extends BlockEntity implements Men
|
|||||||
public void markDirty() {
|
public void markDirty() {
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clientTick(ClientLevel level, long time, BlockState state, BlockPos pos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void firstTick(Level level, BlockState state, BlockPos pos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.block.entity.custom.renderer;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.world.phys.AABB;
|
|
||||||
import net.xevianlight.aphelion.block.entity.custom.RocketAssemblerBlockEntity;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class RocketAssemblerBlockEntityRenderer implements BlockEntityRenderer<RocketAssemblerBlockEntity> {
|
|
||||||
|
|
||||||
public RocketAssemblerBlockEntityRenderer (BlockEntityRendererProvider.Context context) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(@NotNull RocketAssemblerBlockEntity be, float v, @NotNull PoseStack poseStack, @NotNull MultiBufferSource multiBufferSource, int i, int i1) {
|
|
||||||
if (!Minecraft.getInstance().gui.getDebugOverlay().showDebugScreen()) return;
|
|
||||||
|
|
||||||
if (be.getPadBounds() == null) return;
|
|
||||||
BlockPos min = be.getPadBounds().min();
|
|
||||||
BlockPos max = be.getPadBounds().max();
|
|
||||||
|
|
||||||
AABB box = new AABB(
|
|
||||||
min.getX(), min.getY(), min.getZ(),
|
|
||||||
max.getX() + 1, max.getY() + 1, max.getZ() + 1
|
|
||||||
);
|
|
||||||
|
|
||||||
poseStack.pushPose();
|
|
||||||
poseStack.translate(-be.getBlockPos().getX(), -be.getBlockPos().getY(), -be.getBlockPos().getZ());
|
|
||||||
|
|
||||||
VertexConsumer vc = multiBufferSource.getBuffer(RenderType.lines());
|
|
||||||
|
|
||||||
LevelRenderer.renderLineBox(poseStack, vc, box, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
poseStack.popPose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ public class ModBlockEntities {
|
|||||||
RocketAssemblerBlockEntity::new, ModBlocks.ROCKET_ASSEMBLER_BLOCK.get()).build(null)
|
RocketAssemblerBlockEntity::new, ModBlocks.ROCKET_ASSEMBLER_BLOCK.get()).build(null)
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final Supplier<BlockEntityType<PipeTestBlockEntity>> PIPE_TEST_BLOCK_ENTITY =
|
public static final Supplier<BlockEntityType<GravityTestBlockEntity>> GRAVITY_TEST_BLOCK_ENTITY =
|
||||||
BLOCK_ENTITIES.register("pipe_test_block_entity", () -> BlockEntityType.Builder.of(
|
BLOCK_ENTITIES.register("gravity_test_block_entity", () -> BlockEntityType.Builder.of(
|
||||||
PipeTestBlockEntity::new, ModBlocks.PIPE_TEST_BLOCK.get()).build(null)
|
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);
|
||||||
@@ -19,6 +20,6 @@ public class ModBlocks {
|
|||||||
public static final DeferredBlock<Block> VACUUM_ARC_FURNACE_CONTROLLER = BLOCKS.register("vacuum_arc_furnace_controller", () -> new VacuumArcFurnaceController(VacuumArcFurnaceController.getProperties()));
|
public static final DeferredBlock<Block> VACUUM_ARC_FURNACE_CONTROLLER = BLOCKS.register("vacuum_arc_furnace_controller", () -> new VacuumArcFurnaceController(VacuumArcFurnaceController.getProperties()));
|
||||||
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_assembler_block", () -> 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> PIPE_TEST_BLOCK = BLOCKS.register("pipe", () -> new PipeTestBlock(PipeTestBlock.getProperties()));
|
public static final DeferredBlock<Block> GRAVITY_TEST_BLOCK = BLOCKS.register("gravity_test_block", () -> new GravityTestBlock(GravityTestBlock.getProperties()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,5 @@ public class ModCreativeTabs {
|
|||||||
output.accept(ModItems.ARC_FURNACE_CASING_BLOCK);
|
output.accept(ModItems.ARC_FURNACE_CASING_BLOCK);
|
||||||
output.accept(ModItems.VACUUM_ARC_FURNACE_CONTROLLER);
|
output.accept(ModItems.VACUUM_ARC_FURNACE_CONTROLLER);
|
||||||
output.accept(ModItems.LAUNCH_PAD);
|
output.accept(ModItems.LAUNCH_PAD);
|
||||||
output.accept(ModItems.ROCKET_ASSEMBLER_BLOCK);
|
|
||||||
}).build());
|
}).build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +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> PIPE_TEST_BLOCK = ITEMS.register("pipe", () -> new BlockItem(ModBlocks.PIPE_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> ROCKET_ASSEMBLER_BLOCK = ITEMS.register("rocket_assembler_block", () -> new BlockItem(ModBlocks.ROCKET_ASSEMBLER_BLOCK.get(), RocketAssemblerBlock.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()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,8 +103,9 @@ public class EnvironmentSavedData extends SavedData {
|
|||||||
|
|
||||||
public void setOxygen(Level level, BlockPos pos, boolean value) {
|
public void setOxygen(Level level, BlockPos pos, boolean value) {
|
||||||
var data = getDataForPosition(level, pos);
|
var data = getDataForPosition(level, pos);
|
||||||
|
data.setOxygen(value);
|
||||||
// Aphelion.LOGGER.info("Set oxygen for {} to {}", pos, value);
|
// Aphelion.LOGGER.info("Set oxygen for {} to {}", pos, value);
|
||||||
putOrRemove(level, pos.asLong(), data.withOxygen(value).pack());
|
putOrRemove(level, pos.asLong(), data.pack());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOxygen(Level level, Collection<BlockPos> positions, boolean value) {
|
public void setOxygen(Level level, Collection<BlockPos> positions, boolean value) {
|
||||||
@@ -115,7 +116,8 @@ public class EnvironmentSavedData extends SavedData {
|
|||||||
|
|
||||||
public void resetOxygen(Level level, BlockPos pos) {
|
public void resetOxygen(Level level, BlockPos pos) {
|
||||||
var data = getDataForPosition(level, pos);
|
var data = getDataForPosition(level, pos);
|
||||||
putOrRemove(level, pos.asLong(), data.withOxygen(defaultData(level).hasOxygen()).pack());
|
data.setOxygen(defaultData(level).hasOxygen());
|
||||||
|
putOrRemove(level, pos.asLong(), data.pack());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetOxygen(Level level, Collection<BlockPos> positions) {
|
public void resetOxygen(Level level, Collection<BlockPos> positions) {
|
||||||
@@ -131,7 +133,8 @@ public class EnvironmentSavedData extends SavedData {
|
|||||||
|
|
||||||
public void setGravity(Level level, BlockPos pos, float value) {
|
public void setGravity(Level level, BlockPos pos, float value) {
|
||||||
var data = getDataForPosition(level, pos);
|
var data = getDataForPosition(level, pos);
|
||||||
putOrRemove(level, pos.asLong(), data.withGravity(value).pack());
|
data.setGravity(value);
|
||||||
|
putOrRemove(level, pos.asLong(), data.pack());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGravity(Level level, Collection<BlockPos> positions, float value) {
|
public void setGravity(Level level, Collection<BlockPos> positions, float value) {
|
||||||
@@ -142,7 +145,8 @@ public class EnvironmentSavedData extends SavedData {
|
|||||||
|
|
||||||
public void resetGravity(Level level, BlockPos pos) {
|
public void resetGravity(Level level, BlockPos pos) {
|
||||||
var data = getDataForPosition(level, pos);
|
var data = getDataForPosition(level, pos);
|
||||||
putOrRemove(level, pos.asLong(), data.withGravity(defaultData(level).getGravity()).pack());
|
data.setGravity(defaultData(level).getGravity());
|
||||||
|
putOrRemove(level, pos.asLong(), data.pack());
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getTemperature(Level level, BlockPos pos) {
|
public short getTemperature(Level level, BlockPos pos) {
|
||||||
@@ -152,7 +156,8 @@ public class EnvironmentSavedData extends SavedData {
|
|||||||
|
|
||||||
public void setTemperature(Level level, BlockPos pos, short value) {
|
public void setTemperature(Level level, BlockPos pos, short value) {
|
||||||
var data = getDataForPosition(level, pos);
|
var data = getDataForPosition(level, pos);
|
||||||
putOrRemove(level, pos.asLong(), data.withTemperature(value).pack());
|
data.setTemperature(value);
|
||||||
|
putOrRemove(level, pos.asLong(), data.pack());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTemperature(Level level, Collection<BlockPos> positions, short value) {
|
public void setTemperature(Level level, Collection<BlockPos> positions, short value) {
|
||||||
@@ -163,7 +168,8 @@ public class EnvironmentSavedData extends SavedData {
|
|||||||
|
|
||||||
public void resetTemperature(Level level, BlockPos pos) {
|
public void resetTemperature(Level level, BlockPos pos) {
|
||||||
var data = getDataForPosition(level, pos);
|
var data = getDataForPosition(level, pos);
|
||||||
putOrRemove(level, pos.asLong(), data.withTemperature((defaultData(level).getTemperature())).pack());
|
data.setTemperature(defaultData(level).getTemperature());
|
||||||
|
putOrRemove(level, pos.asLong(), data.pack());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putOrRemove(Level level, long key, int packed) {
|
private void putOrRemove(Level level, long key, int packed) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package net.xevianlight.aphelion.core.saveddata;
|
package net.xevianlight.aphelion.core.saveddata;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
@@ -8,6 +10,8 @@ import net.minecraft.nbt.Tag;
|
|||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.saveddata.SavedData;
|
import net.minecraft.world.level.saveddata.SavedData;
|
||||||
|
import net.xevianlight.aphelion.client.ClientOxygenCache;
|
||||||
|
import net.xevianlight.aphelion.core.saveddata.types.EnvironmentData;
|
||||||
import net.xevianlight.aphelion.core.saveddata.types.GravityData;
|
import net.xevianlight.aphelion.core.saveddata.types.GravityData;
|
||||||
import net.xevianlight.aphelion.planet.Planet;
|
import net.xevianlight.aphelion.planet.Planet;
|
||||||
import net.xevianlight.aphelion.planet.PlanetCache;
|
import net.xevianlight.aphelion.planet.PlanetCache;
|
||||||
@@ -15,6 +19,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,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
|
||||||
@@ -55,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]);
|
||||||
}
|
}
|
||||||
@@ -76,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;
|
||||||
}
|
}
|
||||||
@@ -89,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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,7 +114,7 @@ public class GravitySavedData extends SavedData {
|
|||||||
List<GravityData> regions = getGravityRegions(pos);
|
List<GravityData> regions = getGravityRegions(pos);
|
||||||
|
|
||||||
for (var e : regions) {
|
for (var e : regions) {
|
||||||
sum += e.getGravity();
|
sum += e.getAccel();
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
@@ -110,15 +124,19 @@ 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);
|
||||||
|
|
||||||
for (var e : regions) {
|
for (var e : regions) {
|
||||||
var accel = e.getGravity();
|
var accel = e.getAccel();
|
||||||
if (accel > max) max = accel;
|
if (accel > max) max = accel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (max == -1) {
|
||||||
|
max = defaultGravity(this.level);
|
||||||
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.xevianlight.aphelion.core.saveddata.types;
|
package net.xevianlight.aphelion.core.saveddata.types;
|
||||||
|
|
||||||
public record EnvironmentData (boolean oxygen, short temperature, float gravity){
|
public final class EnvironmentData {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -26,6 +26,9 @@ public record EnvironmentData (boolean oxygen, short temperature, float gravity)
|
|||||||
private static final int TEMPERATURE_BIT = OXYGEN_BIT + OXYGEN_BITS; // next 16 bits
|
private static final int TEMPERATURE_BIT = OXYGEN_BIT + OXYGEN_BITS; // next 16 bits
|
||||||
private static final int GRAVITY_BIT = TEMPERATURE_BIT + TEMPERATURE_BITS; // next 15 bits
|
private static final int GRAVITY_BIT = TEMPERATURE_BIT + TEMPERATURE_BITS; // next 15 bits
|
||||||
|
|
||||||
|
private boolean oxygen;
|
||||||
|
private short temperature;
|
||||||
|
private float gravity;
|
||||||
|
|
||||||
public EnvironmentData(boolean oxygen, short temperature, float gravity) {
|
public EnvironmentData(boolean oxygen, short temperature, float gravity) {
|
||||||
this.oxygen = oxygen;
|
this.oxygen = oxygen;
|
||||||
@@ -33,19 +36,6 @@ public record EnvironmentData (boolean oxygen, short temperature, float gravity)
|
|||||||
this.gravity = gravity;
|
this.gravity = gravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnvironmentData withOxygen(boolean newOxygen) {
|
|
||||||
return new EnvironmentData(newOxygen, this.temperature, this.gravity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnvironmentData withTemperature(short newTemperature) {
|
|
||||||
return new EnvironmentData(this.oxygen, newTemperature, this.gravity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public EnvironmentData withGravity(float newGravity) {
|
|
||||||
return new EnvironmentData(this.oxygen, this.temperature, newGravity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int pack() {
|
public int pack() {
|
||||||
int packedData = 0;
|
int packedData = 0;
|
||||||
|
|
||||||
@@ -86,12 +76,23 @@ public record EnvironmentData (boolean oxygen, short temperature, float gravity)
|
|||||||
return oxygen;
|
return oxygen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOxygen(boolean oxygen) {
|
||||||
|
this.oxygen = oxygen;
|
||||||
|
}
|
||||||
|
|
||||||
public short getTemperature() {
|
public short getTemperature() {
|
||||||
return temperature;
|
return temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTemperature(short temperature) {
|
||||||
|
this.temperature = temperature;
|
||||||
|
}
|
||||||
|
|
||||||
public float getGravity() {
|
public float getGravity() {
|
||||||
return gravity;
|
return gravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGravity(float gravity) {
|
||||||
|
this.gravity = gravity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,50 @@
|
|||||||
package net.xevianlight.aphelion.core.saveddata.types;
|
package net.xevianlight.aphelion.core.saveddata.types;
|
||||||
|
|
||||||
// A record seems more useful here since this class is really only to help us interpret these values as they are written to the disk as an integer.
|
public class GravityData {
|
||||||
// We never store GravityData for any reason other than to test its values or to pack it into an integer.
|
private float accel;
|
||||||
public record GravityData (float gravity, float radius) {
|
private float radius;
|
||||||
|
|
||||||
public static final float DEFAULT_GRAVITY = 32.00f; // Vanilla acceleration
|
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;
|
||||||
public static final float MAX_GRAVITY = Short.MAX_VALUE / GRAVITY_PRECISION;
|
public static final float MAX_GRAVITY = Short.MAX_VALUE / GRAVITY_PRECISION;
|
||||||
|
|
||||||
public GravityData {
|
public GravityData(float accel, float radius) {
|
||||||
gravity = Math.clamp(gravity, 0f, MAX_GRAVITY);
|
this.accel = accel;
|
||||||
radius = Math.clamp(radius, 0f, MAX_RADIUS);
|
this.radius = radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int pack() {
|
public int pack() {
|
||||||
int g = Math.round(gravity * GRAVITY_PRECISION) & 0xFFFF;
|
int packed = 0;
|
||||||
int r = Math.round(radius * RADIUS_PRECISION) & 0xFFFF;
|
|
||||||
|
|
||||||
return g | (r << 16);
|
packed |= (int) (this.accel * GRAVITY_PRECISION);
|
||||||
|
packed |= (int) (this.radius * RADIUS_PRECISION) << 16;
|
||||||
|
|
||||||
|
return packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getGravity() {
|
public float getAccel() {
|
||||||
return gravity;
|
return accel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccel(float accel) {
|
||||||
|
this.accel = accel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getRadius() {
|
public float getRadius() {
|
||||||
return radius;
|
return radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GravityData unpack(int packed) {
|
public void setRadius(short radius) {
|
||||||
float gravity = (packed & 0xFFFF) / GRAVITY_PRECISION;
|
this.radius = radius;
|
||||||
float radius = ((packed >>> 16) & 0xFFFF) / RADIUS_PRECISION;
|
}
|
||||||
|
|
||||||
return new GravityData(gravity, radius);
|
public static GravityData unpack(int packed) {
|
||||||
|
float accel = (packed & 0xFFFF) / GRAVITY_PRECISION;
|
||||||
|
float radius = (packed >> 16) / RADIUS_PRECISION;
|
||||||
|
|
||||||
|
return new GravityData(accel, radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ 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());
|
dropSelf(ModBlocks.ROCKET_ASSEMBLER_BLOCK.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,6 @@ public class ModBlockStateProvider extends BlockStateProvider {
|
|||||||
blockItem(ModBlocks.ELECTRIC_ARC_FURNACE);
|
blockItem(ModBlocks.ELECTRIC_ARC_FURNACE);
|
||||||
blockItem(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER);
|
blockItem(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER);
|
||||||
|
|
||||||
// horizontalBlock(ModBlocks.ROCKET_ASSEMBLER_BLOCK.get(), models().orientable("aphelion:rocket_assembler_block",
|
|
||||||
// modLoc("block/test_block"),
|
|
||||||
// mcLoc("block/furnace_front"),
|
|
||||||
// modLoc("block/test_block")));
|
|
||||||
blockItem(ModBlocks.ROCKET_ASSEMBLER_BLOCK);
|
|
||||||
|
|
||||||
blockWithItem(ModBlocks.BLOCK_STEEL);
|
blockWithItem(ModBlocks.BLOCK_STEEL);
|
||||||
blockWithItem(ModBlocks.DIMENSION_CHANGER);
|
blockWithItem(ModBlocks.DIMENSION_CHANGER);
|
||||||
|
|
||||||
@@ -38,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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.systems.conveyor;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.neoforged.neoforge.capabilities.BlockCapabilityCache;
|
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
|
||||||
import net.neoforged.neoforge.items.IItemHandler;
|
|
||||||
import net.xevianlight.aphelion.block.entity.custom.PipeTestBlockEntity;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class BasicItemExtractAttachment extends ConveyorAttachment implements ConveyorInput {
|
|
||||||
|
|
||||||
BlockCapabilityCache<IItemHandler, @Nullable Direction> capabilityCache;
|
|
||||||
|
|
||||||
public BasicItemExtractAttachment(ServerLevel level, BlockPos pos, Direction facingDirection) {
|
|
||||||
super(level, pos, facingDirection);
|
|
||||||
|
|
||||||
capabilityCache = BlockCapabilityCache.create(
|
|
||||||
Capabilities.ItemHandler.BLOCK,
|
|
||||||
level,
|
|
||||||
pos.relative(facingDirection),
|
|
||||||
facingDirection.getOpposite()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick(ServerLevel level, BlockState state, BlockPos pos, Direction facingDirection, ConveyorNetwork network) {
|
|
||||||
// do an extract and distribute
|
|
||||||
IItemHandler container = capabilityCache.getCapability();
|
|
||||||
if (container == null) return;
|
|
||||||
|
|
||||||
final int EXTRACT_PER_TICK = 4;
|
|
||||||
int to_extract = EXTRACT_PER_TICK;
|
|
||||||
|
|
||||||
int extract_slot_id = container.getSlots() - 1;
|
|
||||||
while (extract_slot_id >= 0 && container.getStackInSlot(extract_slot_id).isEmpty()) extract_slot_id--;
|
|
||||||
if (extract_slot_id == -1) return;
|
|
||||||
|
|
||||||
|
|
||||||
// Do a simulated extract, then run through every output side on the graph and do real inserts.
|
|
||||||
// By the end, remove as many items as we successfully inserted with a real extract
|
|
||||||
ItemStack to_distribute = container.extractItem(extract_slot_id, to_extract, true);
|
|
||||||
int extracted_amount = to_distribute.getCount();
|
|
||||||
|
|
||||||
to_distribute = network.insertItem(to_distribute, false);
|
|
||||||
|
|
||||||
int distributed_amount = extracted_amount;
|
|
||||||
if (!to_distribute.isEmpty()) {
|
|
||||||
distributed_amount = extracted_amount - to_distribute.getCount();
|
|
||||||
}
|
|
||||||
container.extractItem(extract_slot_id, distributed_amount, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.systems.conveyor;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.neoforged.neoforge.capabilities.BlockCapabilityCache;
|
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
|
||||||
import net.neoforged.neoforge.items.IItemHandler;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class BasicItemOutput implements ConveyorOutput {
|
|
||||||
BlockCapabilityCache<IItemHandler, @Nullable Direction> capabilityCache;
|
|
||||||
|
|
||||||
public BasicItemOutput(ServerLevel level, BlockPos pos, Direction facingDirection) {
|
|
||||||
capabilityCache = BlockCapabilityCache.create(
|
|
||||||
Capabilities.ItemHandler.BLOCK,
|
|
||||||
level,
|
|
||||||
pos.relative(facingDirection),
|
|
||||||
facingDirection.getOpposite()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack insertItem(ItemStack stack, boolean simulate) {
|
|
||||||
ItemStack toInsert = stack.copy();
|
|
||||||
|
|
||||||
IItemHandler container = capabilityCache.getCapability();
|
|
||||||
if (container == null) return toInsert;
|
|
||||||
|
|
||||||
for (int insertIndex = 0; insertIndex < container.getSlots(); insertIndex++) {
|
|
||||||
if (toInsert.isEmpty()) break;
|
|
||||||
|
|
||||||
toInsert = container.insertItem(insertIndex, toInsert, simulate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return toInsert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.systems.conveyor;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.xevianlight.aphelion.block.entity.custom.PipeTestBlockEntity;
|
|
||||||
|
|
||||||
public class ConveyorAttachment {
|
|
||||||
ConveyorAttachment(ServerLevel level, BlockPos pos, Direction facingDirection) {}
|
|
||||||
|
|
||||||
//TODO: put in the right interface for a render function
|
|
||||||
void render() {};
|
|
||||||
|
|
||||||
public void tick(ServerLevel level, BlockState state, BlockPos pos, Direction facingDirection, ConveyorNetwork network) {}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.systems.conveyor;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
|
|
||||||
public interface ConveyorInput {
|
|
||||||
void tick(ServerLevel level, BlockState state, BlockPos pos, Direction facingDirection, ConveyorNetwork graph);
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.systems.conveyor;
|
|
||||||
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.xevianlight.aphelion.block.entity.custom.PipeTestBlockEntity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
// I'm naming and structuring the conveyor stuff like this bc i kinda wanna try making a space-engineers
|
|
||||||
// style request system later... though it might not be necessary, given that the reason it needs to be like that
|
|
||||||
// in space engineers is mostly space constraints if i had to guess
|
|
||||||
public class ConveyorNetwork {
|
|
||||||
boolean isInvalid = false;
|
|
||||||
public List<PipeTestBlockEntity> pipes = new ArrayList<>();
|
|
||||||
public Set<ConveyorOutput> outputs = new HashSet<>();
|
|
||||||
|
|
||||||
public ItemStack insertItem(ItemStack stack, boolean simulate) {
|
|
||||||
if (isInvalid) return stack;
|
|
||||||
for (ConveyorOutput output : outputs) {
|
|
||||||
stack = output.insertItem(stack, simulate);
|
|
||||||
if (stack.isEmpty()) break;
|
|
||||||
}
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addPipe(PipeTestBlockEntity pipe) {
|
|
||||||
pipes.add(pipe);
|
|
||||||
pipe.graph = this;
|
|
||||||
for (ConveyorOutput output : pipe.outputs.values()) {
|
|
||||||
if (output != null) this.outputs.add(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called whenever a pipe is removed from a graph, or when a new graph comes across an old one.
|
|
||||||
public void invalidate() {
|
|
||||||
for (PipeTestBlockEntity pipe : pipes) {
|
|
||||||
pipe.graph = null;
|
|
||||||
for (ConveyorOutput output : pipe.outputs.values()) {
|
|
||||||
if (output != null) this.outputs.remove(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.isInvalid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.systems.conveyor;
|
|
||||||
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
|
|
||||||
public interface ConveyorOutput {
|
|
||||||
/// @return Rejected items
|
|
||||||
ItemStack insertItem(ItemStack stack, boolean simulate);
|
|
||||||
}
|
|
||||||
@@ -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": [
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"multipart": [
|
|
||||||
{ "apply": { "model": "aphelion:block/pipe_core" }},
|
|
||||||
{ "when": { "north": "true" }, "apply": { "model": "aphelion:block/pipe_side" }},
|
|
||||||
{ "when": { "east": "true" }, "apply": { "model": "aphelion:block/pipe_side", "y": 90 }},
|
|
||||||
{ "when": { "south": "true" }, "apply": { "model": "aphelion:block/pipe_side", "y": 180 }},
|
|
||||||
{ "when": { "west": "true" }, "apply": { "model": "aphelion:block/pipe_side", "y": 270 }},
|
|
||||||
{ "when": { "up": "true" }, "apply": { "model": "aphelion:block/pipe_side", "x": 270 }},
|
|
||||||
{ "when": { "down": "true" }, "apply": { "model": "aphelion:block/pipe_side", "x": 90 }}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"variants": {
|
|
||||||
"facing=east,formed=false": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block",
|
|
||||||
"y": 90
|
|
||||||
},
|
|
||||||
"facing=north,formed=false": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block"
|
|
||||||
},
|
|
||||||
"facing=south,formed=false": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block",
|
|
||||||
"y": 180
|
|
||||||
},
|
|
||||||
"facing=west,formed=false": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block",
|
|
||||||
"y": 270
|
|
||||||
},
|
|
||||||
"facing=east,formed=true": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block_formed",
|
|
||||||
"y": 90
|
|
||||||
},
|
|
||||||
"facing=north,formed=true": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block_formed"
|
|
||||||
},
|
|
||||||
"facing=south,formed=true": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block_formed",
|
|
||||||
"y": 180
|
|
||||||
},
|
|
||||||
"facing=west,formed=true": {
|
|
||||||
"model": "aphelion:block/rocket_assembler_block_formed",
|
|
||||||
"y": 270
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"ambientocclusion": false,
|
|
||||||
"textures": {
|
|
||||||
"texture": "aphelion:block/pipe_texture"
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"from": [ 6, 6, 6 ],
|
|
||||||
"to": [ 10, 10, 10 ],
|
|
||||||
"faces": {
|
|
||||||
"down": { "texture": "#texture", "uv": [ 6, 6, 10, 10 ] },
|
|
||||||
"up": { "texture": "#texture", "uv": [ 6, 6, 10, 10 ] },
|
|
||||||
"north": { "texture": "#texture", "uv": [ 6, 6, 10, 10 ] },
|
|
||||||
"south": { "texture": "#texture", "uv": [ 6, 6, 10, 10 ] },
|
|
||||||
"west": { "texture": "#texture", "uv": [ 6, 6, 10, 10 ] },
|
|
||||||
"east": { "texture": "#texture", "uv": [ 6, 6, 10, 10 ] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"textures": {
|
|
||||||
"texture": "aphelion:block/pipe_texture"
|
|
||||||
},
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"from": [ 6, 6, 0 ],
|
|
||||||
"to": [ 10, 10, 6 ],
|
|
||||||
"faces": {
|
|
||||||
"down": { "texture": "#texture", "uv": [ 6, 0, 10, 6 ] },
|
|
||||||
"up": { "texture": "#texture", "uv": [ 6, 0, 10, 6 ] },
|
|
||||||
"north": { "texture": "#texture", "uv": [ 6, 6, 10, 10 ] },
|
|
||||||
"west": { "texture": "#texture", "uv": [ 0, 6, 6, 10 ] },
|
|
||||||
"east": { "texture": "#texture", "uv": [ 0, 6, 6, 10 ] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"parent": "minecraft:block/orientable",
|
|
||||||
"textures": {
|
|
||||||
"front": "minecraft:block/furnace_front",
|
|
||||||
"side": "aphelion:block/test_block",
|
|
||||||
"top": "aphelion:block/test_block"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"parent": "minecraft:block/orientable",
|
|
||||||
"textures": {
|
|
||||||
"front": "minecraft:block/furnace_front",
|
|
||||||
"side": "aphelion:block/arc_furnace_casing_formed",
|
|
||||||
"top": "aphelion:block/arc_furnace_casing_formed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 280 B |
Binary file not shown.
|
Before Width: | Height: | Size: 374 B |
Binary file not shown.
|
Before Width: | Height: | Size: 247 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