mirror of
https://github.com/XevianLight/Aphelion.git
synced 2026-05-11 01:50:56 +01:00
RocketEntity added. Uses RocketRenderer and RocketStructure to render blocks. RocketStructure supports volumes up to 128^3.
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
// 1.21.1 2026-01-18T19:51:57.3558369 Loot Tables
|
// 1.21.1 2026-01-23T22:32:50.7204827 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
|
||||||
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
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// 1.21.1 2026-01-17T21:22:18.4350515 Tags for minecraft:block mod id aphelion
|
// 1.21.1 2026-01-23T22:32:50.7214756 Tags for minecraft:block mod id aphelion
|
||||||
058c56a0c17204ed5d9cadaffae84292b4752213 data/c/tags/block/storage_blocks.json
|
058c56a0c17204ed5d9cadaffae84292b4752213 data/c/tags/block/storage_blocks.json
|
||||||
058c56a0c17204ed5d9cadaffae84292b4752213 data/c/tags/block/storage_blocks/steel.json
|
058c56a0c17204ed5d9cadaffae84292b4752213 data/c/tags/block/storage_blocks/steel.json
|
||||||
51e9ab2ffa3ba81700cbaab7f39985bb2ab673fa data/minecraft/tags/block/mineable/pickaxe.json
|
7d420216f15b8f78d2a3b298f9bb773a9e5f79c3 data/minecraft/tags/block/mineable/pickaxe.json
|
||||||
51e9ab2ffa3ba81700cbaab7f39985bb2ab673fa data/minecraft/tags/block/needs_stone_tool.json
|
7d420216f15b8f78d2a3b298f9bb773a9e5f79c3 data/minecraft/tags/block/needs_stone_tool.json
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
"aphelion:test_block",
|
"aphelion:test_block",
|
||||||
"aphelion:electric_arc_furnace",
|
"aphelion:electric_arc_furnace",
|
||||||
"aphelion:block_steel",
|
"aphelion:block_steel",
|
||||||
"aphelion:arc_furnace_casing"
|
"aphelion:arc_furnace_casing",
|
||||||
|
"aphelion:vacuum_arc_furnace_controller",
|
||||||
|
"aphelion:vaf_dummy_block"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
"aphelion:test_block",
|
"aphelion:test_block",
|
||||||
"aphelion:electric_arc_furnace",
|
"aphelion:electric_arc_furnace",
|
||||||
"aphelion:block_steel",
|
"aphelion:block_steel",
|
||||||
"aphelion:arc_furnace_casing"
|
"aphelion:arc_furnace_casing",
|
||||||
|
"aphelion:vacuum_arc_furnace_controller",
|
||||||
|
"aphelion:vaf_dummy_block"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
package net.xevianlight.aphelion;
|
package net.xevianlight.aphelion;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.entity.ThrownItemRenderer;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.neoforged.api.distmarker.Dist;
|
import net.neoforged.api.distmarker.Dist;
|
||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
||||||
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
|
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
|
||||||
import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent;
|
import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent;
|
||||||
|
import net.neoforged.neoforge.event.AddReloadListenerEvent;
|
||||||
import net.xevianlight.aphelion.block.dummy.renderer.MultiblockDummyRenderer;
|
import net.xevianlight.aphelion.block.dummy.renderer.MultiblockDummyRenderer;
|
||||||
import net.xevianlight.aphelion.client.AphelionConfig;
|
import net.xevianlight.aphelion.client.AphelionConfig;
|
||||||
|
import net.xevianlight.aphelion.planet.AphelionPlanetJSONLoader;
|
||||||
import net.xevianlight.aphelion.core.init.*;
|
import net.xevianlight.aphelion.core.init.*;
|
||||||
import net.xevianlight.aphelion.fluid.BaseFluidType;
|
import net.xevianlight.aphelion.fluid.BaseFluidType;
|
||||||
import net.xevianlight.aphelion.fluid.ModFluidTypes;
|
import net.xevianlight.aphelion.fluid.ModFluidTypes;
|
||||||
@@ -18,6 +22,7 @@ import net.xevianlight.aphelion.screen.ModMenuTypes;
|
|||||||
import net.xevianlight.aphelion.screen.TestBlockScreen;
|
import net.xevianlight.aphelion.screen.TestBlockScreen;
|
||||||
import net.xevianlight.aphelion.screen.VacuumArcFurnaceScreen;
|
import net.xevianlight.aphelion.screen.VacuumArcFurnaceScreen;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
import net.xevianlight.aphelion.entites.vehicles.RocketRenderer;
|
||||||
|
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
|
|
||||||
@@ -59,6 +64,7 @@ public class Aphelion {
|
|||||||
ModFluids.register(MOD_BUS);
|
ModFluids.register(MOD_BUS);
|
||||||
ModSounds.register(MOD_BUS);
|
ModSounds.register(MOD_BUS);
|
||||||
ModRecipes.register(MOD_BUS);
|
ModRecipes.register(MOD_BUS);
|
||||||
|
ModEntities.register(MOD_BUS);
|
||||||
|
|
||||||
// Register ourselves for server and other game events we are interested in.
|
// Register ourselves for server and other game events we are interested in.
|
||||||
// Note that this is necessary if and only if we want *this* class (ExtremeRocketry) to respond directly to events.
|
// Note that this is necessary if and only if we want *this* class (ExtremeRocketry) to respond directly to events.
|
||||||
@@ -74,6 +80,10 @@ public class Aphelion {
|
|||||||
modContainer.registerConfig(ModConfig.Type.COMMON, AphelionConfig.SPEC);
|
modContainer.registerConfig(ModConfig.Type.COMMON, AphelionConfig.SPEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation id(String path) {
|
||||||
|
return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, path);
|
||||||
|
}
|
||||||
|
|
||||||
private void commonSetup(FMLCommonSetupEvent event) {
|
private void commonSetup(FMLCommonSetupEvent event) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -97,6 +107,12 @@ public class Aphelion {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onAddReloadListeners(AddReloadListenerEvent event) {
|
||||||
|
// Set up the planet json listener. This reloads on /reload
|
||||||
|
event.addListener(new AphelionPlanetJSONLoader());
|
||||||
|
}
|
||||||
|
|
||||||
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
|
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
|
||||||
@EventBusSubscriber(modid = MOD_ID, value = Dist.CLIENT)
|
@EventBusSubscriber(modid = MOD_ID, value = Dist.CLIENT)
|
||||||
public static class ClientModEvents {
|
public static class ClientModEvents {
|
||||||
@@ -124,5 +140,10 @@ public class Aphelion {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
|
||||||
|
event.registerEntityRenderer(ModEntities.ROCKET.get(), RocketRenderer::new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ public class VacuumArcFurnaceController extends BaseEntityBlock {
|
|||||||
.sound(SoundType.NETHERITE_BLOCK)
|
.sound(SoundType.NETHERITE_BLOCK)
|
||||||
.destroyTime(2f)
|
.destroyTime(2f)
|
||||||
.explosionResistance(10f)
|
.explosionResistance(10f)
|
||||||
.requiresCorrectToolForDrops();
|
.requiresCorrectToolForDrops()
|
||||||
|
.lightLevel(state -> state.getValue(BlockStateProperties.LIT) ? 15 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Item.Properties getItemProperties() {
|
public static Item.Properties getItemProperties() {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
public class BaseMultiblockDummyBlockEntity extends BlockEntity implements IMultiblockPart {
|
public class BaseMultiblockDummyBlockEntity extends BlockEntity implements IMultiblockPart {
|
||||||
@Nullable private BlockPos controllerPos;
|
@Nullable private BlockPos controllerPos;
|
||||||
private BlockState mimicing = Blocks.AIR.defaultBlockState();
|
private BlockState mimicking = Blocks.AIR.defaultBlockState();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ItemStackHandler getControllerInventory() {
|
private ItemStackHandler getControllerInventory() {
|
||||||
@@ -116,7 +116,7 @@ public class BaseMultiblockDummyBlockEntity extends BlockEntity implements IMult
|
|||||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
super.saveAdditional(tag, registries);
|
super.saveAdditional(tag, registries);
|
||||||
if (controllerPos != null) tag.putLong("controller", controllerPos.asLong());
|
if (controllerPos != null) tag.putLong("controller", controllerPos.asLong());
|
||||||
tag.put("mimic", NbtUtils.writeBlockState(mimicing));
|
tag.put("mimic", NbtUtils.writeBlockState(mimicking));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -170,12 +170,12 @@ public class BaseMultiblockDummyBlockEntity extends BlockEntity implements IMult
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getMimicing() {
|
public BlockState getMimicing() {
|
||||||
return mimicing;
|
return mimicking;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMimicing(BlockState newState) {
|
public void setMimicing(BlockState newState) {
|
||||||
mimicing = newState;
|
mimicking = newState;
|
||||||
setChanged();
|
setChanged();
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 3);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.xevianlight.aphelion.client;
|
package net.xevianlight.aphelion.client;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.DimensionSpecialEffects;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||||
import net.neoforged.api.distmarker.Dist;
|
import net.neoforged.api.distmarker.Dist;
|
||||||
@@ -44,6 +43,7 @@ public class AphelionClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void onAddReloadListener(BiConsumer<ResourceLocation, PreparableReloadListener> consumer) {
|
public static void onAddReloadListener(BiConsumer<ResourceLocation, PreparableReloadListener> consumer) {
|
||||||
|
// Set up the dimension renderers json listener. This reloads on F3+T
|
||||||
consumer.accept(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "planet_renderers"), new AphelionDimensionRenderers());
|
consumer.accept(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "planet_renderers"), new AphelionDimensionRenderers());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public class AphelionClient {
|
|||||||
public static void onRegisterDimensionEffects(RegisterDimensionSpecialEffectsEvent event) {
|
public static void onRegisterDimensionEffects(RegisterDimensionSpecialEffectsEvent event) {
|
||||||
event.register(
|
event.register(
|
||||||
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space"),
|
ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space"),
|
||||||
new net.xevianlight.aphelion.client.dimension.SpaceSkyEffects()
|
new net.xevianlight.aphelion.client.dimension.SpaceSkyEffects(null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.xevianlight.aphelion.client;
|
|||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
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.api.distmarker.Dist;
|
import net.neoforged.api.distmarker.Dist;
|
||||||
@@ -21,13 +22,16 @@ public class AphelionDebugOverlay {
|
|||||||
Minecraft mc = Minecraft.getInstance();
|
Minecraft mc = Minecraft.getInstance();
|
||||||
if (mc.level == null || mc.player == null) return;
|
if (mc.level == null || mc.player == null) return;
|
||||||
|
|
||||||
// Only show in your space dimension (optional)
|
// // Only show in your space dimension (optional)
|
||||||
if (!mc.level.dimension().location().equals(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space"))) {
|
// if (!mc.level.dimension().location().equals(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space"))) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
var camPos = mc.gameRenderer.getMainCamera().getPosition();
|
DimensionType type = mc.level.dimensionType();
|
||||||
ResourceLocation orbitId = SpaceSkyEffects.orbitForPos(camPos);
|
ResourceLocation effectsId = type.effectsLocation();
|
||||||
|
|
||||||
|
var camPos = mc.gameRenderer.getMainCamera();
|
||||||
|
ResourceLocation orbitId = SpaceSkyEffects.resolvedId(effectsId, camPos);
|
||||||
|
|
||||||
DimensionRenderer r = DimensionRendererCache.getOrDefault(orbitId);
|
DimensionRenderer r = DimensionRendererCache.getOrDefault(orbitId);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package net.xevianlight.aphelion.client.dimension;
|
package net.xevianlight.aphelion.client.dimension;
|
||||||
|
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.renderer.DimensionSpecialEffects;
|
import net.minecraft.client.renderer.DimensionSpecialEffects;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.xevianlight.aphelion.Aphelion;
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.client.PartitionClientState;
|
||||||
|
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
@@ -56,5 +59,23 @@ public class DimensionSkyEffects extends DimensionSpecialEffects {
|
|||||||
return new float[]{0,0,0,0};
|
return new float[]{0,0,0,0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation orbitForPos(Vec3 pos) {
|
||||||
|
|
||||||
|
int x = SpacePartitionHelper.get(pos.x);
|
||||||
|
int z = SpacePartitionHelper.get(pos.z);
|
||||||
|
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
if (mc.level == null) return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/default");
|
||||||
|
|
||||||
|
// int px = PartitionClientState.pxOr(0);
|
||||||
|
// int py = PartitionClientState.pyOr(0);
|
||||||
|
var data = ResourceLocation.parse(PartitionClientState.idOrUnknown());
|
||||||
|
|
||||||
|
// var data = SpacePartitionSavedData.get(serverLevel).getOrbitForPartition((int) x, (int) z);
|
||||||
|
if (data != null) return data;
|
||||||
|
|
||||||
|
return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/default");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.client.dimension;
|
|
||||||
|
|
||||||
public class DimensionSkyRenderer {
|
|
||||||
|
|
||||||
DimensionRenderer renderer;
|
|
||||||
|
|
||||||
DimensionSkyRenderer(DimensionRenderer renderer) { this.renderer = renderer; }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package net.xevianlight.aphelion.client.dimension;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
|
|
||||||
public record OrbitSkyDefinition(
|
|
||||||
ResourceLocation id,
|
|
||||||
Vec3 skyColor
|
|
||||||
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -12,14 +12,27 @@ import net.xevianlight.aphelion.Aphelion;
|
|||||||
import net.xevianlight.aphelion.client.PartitionClientState;
|
import net.xevianlight.aphelion.client.PartitionClientState;
|
||||||
import net.xevianlight.aphelion.core.space.SpacePartitionSavedData;
|
import net.xevianlight.aphelion.core.space.SpacePartitionSavedData;
|
||||||
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
public class SpaceSkyEffects extends DimensionSpecialEffects {
|
public class SpaceSkyEffects extends DimensionSpecialEffects {
|
||||||
|
|
||||||
public SpaceSkyEffects() {
|
private final ResourceLocation effectsId;
|
||||||
|
|
||||||
|
public SpaceSkyEffects(@Nullable ResourceLocation effectsId) {
|
||||||
super(192, false, SkyType.NORMAL, false, false);
|
super(192, false, SkyType.NORMAL, false, false);
|
||||||
|
this.effectsId = effectsId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation resolvedId(ResourceLocation effectsId, Camera camera) {
|
||||||
|
if (effectsId == null) {
|
||||||
|
return ResourceLocation.withDefaultNamespace("overworld");
|
||||||
|
}
|
||||||
|
if (effectsId.equals(Aphelion.id("space"))) {
|
||||||
|
return SpaceSkyEffects.orbitForPos(camera.getPosition()); // or inline this logic
|
||||||
|
}
|
||||||
|
return effectsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -49,8 +62,8 @@ public class SpaceSkyEffects extends DimensionSpecialEffects {
|
|||||||
@Override
|
@Override
|
||||||
public boolean isFoggyAt(int i, int i1) {
|
public boolean isFoggyAt(int i, int i1) {
|
||||||
|
|
||||||
ResourceLocation id = orbitForPos(net.minecraft.client.Minecraft.getInstance()
|
ResourceLocation id = resolvedId(effectsId ,net.minecraft.client.Minecraft.getInstance()
|
||||||
.gameRenderer.getMainCamera().getPosition());
|
.gameRenderer.getMainCamera());
|
||||||
|
|
||||||
return DimensionRendererCache.getOrDefault(id).hasThickFog();
|
return DimensionRendererCache.getOrDefault(id).hasThickFog();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.minecraft.commands.Commands;
|
|||||||
import net.minecraft.commands.arguments.*;
|
import net.minecraft.commands.arguments.*;
|
||||||
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
|
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.ClickEvent;
|
import net.minecraft.network.chat.ClickEvent;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.network.chat.ComponentUtils;
|
import net.minecraft.network.chat.ComponentUtils;
|
||||||
@@ -17,10 +18,13 @@ import net.minecraft.network.chat.HoverEvent;
|
|||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.RelativeMovement;
|
import net.minecraft.world.entity.RelativeMovement;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.xevianlight.aphelion.Aphelion;
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
import net.xevianlight.aphelion.core.space.SpacePartitionSavedData;
|
import net.xevianlight.aphelion.core.space.SpacePartitionSavedData;
|
||||||
|
import net.xevianlight.aphelion.entites.vehicles.RocketEntity;
|
||||||
|
import net.xevianlight.aphelion.util.RocketStructure;
|
||||||
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
@@ -62,7 +66,7 @@ public class AphelionCommand {
|
|||||||
SpacePartitionSavedData.get(level).overwriteAllExistingOrbits(orbit);
|
SpacePartitionSavedData.get(level).overwriteAllExistingOrbits(orbit);
|
||||||
|
|
||||||
context.getSource().sendSuccess(
|
context.getSource().sendSuccess(
|
||||||
() -> Component.translatable("command.aphelion.station.orbit.overwriteall", orbit.toString()),
|
() -> Component.translatable("command.aphelion.station.orbit.overwrite_all", orbit.toString()),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -123,7 +127,7 @@ public class AphelionCommand {
|
|||||||
SpacePartitionSavedData.get(level).clearAllOrbits();
|
SpacePartitionSavedData.get(level).clearAllOrbits();
|
||||||
|
|
||||||
context.getSource().sendSuccess(
|
context.getSource().sendSuccess(
|
||||||
() -> Component.translatable("command.aphelion.station.orbit.clearall"),
|
() -> Component.translatable("command.aphelion.station.orbit.clear_all"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -280,6 +284,92 @@ public class AphelionCommand {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.then(Commands.literal("planet")
|
||||||
|
.then(Commands.literal("tp")
|
||||||
|
.then(Commands.argument("dimension", DimensionArgument.dimension())
|
||||||
|
.executes(context -> {
|
||||||
|
|
||||||
|
var player = context.getSource().getEntity();
|
||||||
|
if (player == null || player.getServer() == null) {
|
||||||
|
context.getSource().sendFailure(Component.translatable("command.aphelion.station.teleport.failure"));
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetDim = DimensionArgument.getDimension(context, "dimension");
|
||||||
|
|
||||||
|
ServerLevel targetLevel = player.getServer().getLevel(targetDim.dimension());
|
||||||
|
|
||||||
|
if (targetLevel == null) {
|
||||||
|
context.getSource().sendFailure(Component.translatable("command.aphelion.station.teleport.failure.invalid_level"));
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.teleportTo(targetLevel, player.position().x, player.position().y, player.position().z, EnumSet.noneOf(RelativeMovement.class), player.getYRot(), player.getXRot());
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("rocket")
|
||||||
|
.then(Commands.literal("summon")
|
||||||
|
.executes(context -> {
|
||||||
|
RocketStructure structure = new RocketStructure(s -> {
|
||||||
|
s.add(0,0,0, Blocks.IRON_BLOCK.defaultBlockState());
|
||||||
|
});
|
||||||
|
context.getSource().sendSuccess(() -> Component.translatable("command.aphelion.rocket.spawn.success"), true);
|
||||||
|
RocketEntity rocket = RocketEntity.spawnRocket(context.getSource().getLevel(), context.getSource().getEntity().blockPosition(), structure);
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(Commands.argument("entity", EntityArgument.entity())
|
||||||
|
.then(Commands.literal("structure")
|
||||||
|
.then(Commands.literal("set")
|
||||||
|
.then(Commands.argument("nbt", CompoundTagArgument.compoundTag())
|
||||||
|
.executes(context -> {
|
||||||
|
Entity entity = EntityArgument.getEntity(context, "entity");
|
||||||
|
if (entity instanceof RocketEntity rocket) {
|
||||||
|
RocketStructure structure = new RocketStructure(RocketStructure::clear);
|
||||||
|
structure.load(CompoundTagArgument.getCompoundTag(context, "nbt"));
|
||||||
|
rocket.setStructure(structure);
|
||||||
|
} else {
|
||||||
|
context.getSource().sendFailure(Component.translatable("command.aphelion.rocket.entity_invalid"));
|
||||||
|
}
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("get")
|
||||||
|
.executes(context -> {
|
||||||
|
Entity entity = EntityArgument.getEntity(context, "entity");
|
||||||
|
|
||||||
|
if (entity instanceof RocketEntity rocket) {
|
||||||
|
RocketStructure structure = rocket.getStructure();
|
||||||
|
CompoundTag tag = structure.save();
|
||||||
|
|
||||||
|
Component clickableId = Component.literal(tag.toString())
|
||||||
|
.withStyle(style -> style
|
||||||
|
.withClickEvent(new ClickEvent(
|
||||||
|
ClickEvent.Action.COPY_TO_CLIPBOARD,
|
||||||
|
tag.toString()
|
||||||
|
))
|
||||||
|
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click")))
|
||||||
|
.withColor(ChatFormatting.AQUA)
|
||||||
|
);
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> clickableId,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
context.getSource().sendFailure(Component.translatable("command.aphelion.rocket.entity_invalid"));
|
||||||
|
}
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,5 +40,6 @@ public class ModCreativeTabs {
|
|||||||
output.accept(ModItems.ELECTRIC_ARC_FURNACE);
|
output.accept(ModItems.ELECTRIC_ARC_FURNACE);
|
||||||
output.accept(ModItems.BLOCK_STEEL);
|
output.accept(ModItems.BLOCK_STEEL);
|
||||||
output.accept(ModItems.ARC_FURNACE_CASING_BLOCK);
|
output.accept(ModItems.ARC_FURNACE_CASING_BLOCK);
|
||||||
|
output.accept(ModItems.VACUUM_ARC_FURNACE_CONTROLLER);
|
||||||
}).build());
|
}).build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package net.xevianlight.aphelion.core.init;
|
||||||
|
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.world.entity.EntityType;
|
||||||
|
import net.minecraft.world.entity.MobCategory;
|
||||||
|
import net.neoforged.bus.api.IEventBus;
|
||||||
|
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.entites.vehicles.RocketEntity;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class ModEntities {
|
||||||
|
public static final DeferredRegister<EntityType<?>> ENTITIES =
|
||||||
|
DeferredRegister.create(Registries.ENTITY_TYPE, Aphelion.MOD_ID);
|
||||||
|
|
||||||
|
public static final Supplier<EntityType<RocketEntity>> ROCKET =
|
||||||
|
ENTITIES.register("rocket", () ->
|
||||||
|
EntityType.Builder.<RocketEntity>of(RocketEntity::new, MobCategory.MISC)
|
||||||
|
.sized(0.75f, 2.0f) // tall-ish rocket
|
||||||
|
.clientTrackingRange(8)
|
||||||
|
.updateInterval(1)
|
||||||
|
.build("rocket")
|
||||||
|
);
|
||||||
|
|
||||||
|
public static void register(IEventBus bus) {
|
||||||
|
ENTITIES.register(bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import net.minecraft.core.Holder;
|
|||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
import net.minecraft.data.loot.BlockLootSubProvider;
|
import net.minecraft.data.loot.BlockLootSubProvider;
|
||||||
import net.minecraft.world.flag.FeatureFlags;
|
import net.minecraft.world.flag.FeatureFlags;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.xevianlight.aphelion.core.init.ModBlocks;
|
import net.xevianlight.aphelion.core.init.ModBlocks;
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ public class ModBlockLootTableProvider extends BlockLootSubProvider {
|
|||||||
dropSelf(ModBlocks.ELECTRIC_ARC_FURNACE.get());
|
dropSelf(ModBlocks.ELECTRIC_ARC_FURNACE.get());
|
||||||
dropSelf(ModBlocks.ARC_FURNACE_CASING_BLOCK.get());
|
dropSelf(ModBlocks.ARC_FURNACE_CASING_BLOCK.get());
|
||||||
dropSelf(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get());
|
dropSelf(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get());
|
||||||
|
dropOther(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get(), ItemStack.EMPTY.getItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -23,13 +23,17 @@ public class ModBlockTagProvider extends BlockTagsProvider {
|
|||||||
.add(ModBlocks.TEST_BLOCK.get())
|
.add(ModBlocks.TEST_BLOCK.get())
|
||||||
.add(ModBlocks.ELECTRIC_ARC_FURNACE.get())
|
.add(ModBlocks.ELECTRIC_ARC_FURNACE.get())
|
||||||
.add(ModBlocks.BLOCK_STEEL.get())
|
.add(ModBlocks.BLOCK_STEEL.get())
|
||||||
.add(ModBlocks.ARC_FURNACE_CASING_BLOCK.get());
|
.add(ModBlocks.ARC_FURNACE_CASING_BLOCK.get())
|
||||||
|
.add(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get())
|
||||||
|
.add(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get());
|
||||||
|
|
||||||
tag(BlockTags.NEEDS_STONE_TOOL)
|
tag(BlockTags.NEEDS_STONE_TOOL)
|
||||||
.add(ModBlocks.TEST_BLOCK.get())
|
.add(ModBlocks.TEST_BLOCK.get())
|
||||||
.add(ModBlocks.ELECTRIC_ARC_FURNACE.get())
|
.add(ModBlocks.ELECTRIC_ARC_FURNACE.get())
|
||||||
.add(ModBlocks.BLOCK_STEEL.get())
|
.add(ModBlocks.BLOCK_STEEL.get())
|
||||||
.add(ModBlocks.ARC_FURNACE_CASING_BLOCK.get());
|
.add(ModBlocks.ARC_FURNACE_CASING_BLOCK.get())
|
||||||
|
.add(ModBlocks.VACUUM_ARC_FURNACE_CONTROLLER.get())
|
||||||
|
.add(ModBlocks.VAF_MULTIBLOCK_DUMMY_BLOCK.get());
|
||||||
|
|
||||||
tag(ModTags.Blocks.STORAGE_BLOCKS_STEEL)
|
tag(ModTags.Blocks.STORAGE_BLOCKS_STEEL)
|
||||||
.add(ModBlocks.BLOCK_STEEL.get());
|
.add(ModBlocks.BLOCK_STEEL.get());
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package net.xevianlight.aphelion.entites.vehicles;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
|
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||||
|
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||||
|
import net.minecraft.network.syncher.SynchedEntityData;
|
||||||
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
|
import net.minecraft.world.entity.*;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.neoforged.neoforge.entity.IEntityWithComplexSpawn;
|
||||||
|
import net.neoforged.neoforge.fluids.FluidType;
|
||||||
|
import net.xevianlight.aphelion.core.init.ModEntities;
|
||||||
|
import net.xevianlight.aphelion.util.RocketStructure;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class RocketEntity extends Entity implements IEntityWithComplexSpawn {
|
||||||
|
|
||||||
|
RocketStructure structure = new RocketStructure(s -> {
|
||||||
|
s.add(0,0,0, Blocks.NETHERITE_BLOCK.defaultBlockState());
|
||||||
|
s.add(0,1,0, Blocks.NETHERITE_BLOCK.defaultBlockState());
|
||||||
|
s.add(0,2,0, Blocks.NETHERITE_BLOCK.defaultBlockState());
|
||||||
|
});
|
||||||
|
|
||||||
|
private static final EntityDataAccessor<CompoundTag> STRUCTURE_TAG =
|
||||||
|
SynchedEntityData.defineId(RocketEntity.class, EntityDataSerializers.COMPOUND_TAG);
|
||||||
|
|
||||||
|
public static RocketEntity spawnRocket(Level level, BlockPos pos, RocketStructure structure) {
|
||||||
|
if (level.isClientSide) return null;
|
||||||
|
|
||||||
|
RocketEntity rocket = new RocketEntity(ModEntities.ROCKET.get(), level);
|
||||||
|
|
||||||
|
rocket.moveTo(
|
||||||
|
pos.getX() + 0.5f,
|
||||||
|
pos.getY(),
|
||||||
|
pos.getZ() + 0.5f,
|
||||||
|
0.0f,
|
||||||
|
0.0f
|
||||||
|
);
|
||||||
|
|
||||||
|
rocket.setStructure(structure);
|
||||||
|
level.addFreshEntity(rocket);
|
||||||
|
|
||||||
|
return rocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RocketStructure getStructure() {
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RocketEntity(EntityType<?> type, Level level) {
|
||||||
|
super(type, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
|
builder.define(STRUCTURE_TAG, new CompoundTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStructure(RocketStructure structure) {
|
||||||
|
|
||||||
|
this.structure.clear();
|
||||||
|
CompoundTag tag = structure.save();
|
||||||
|
this.structure.load(tag);
|
||||||
|
this.refreshDimensions();
|
||||||
|
this.setBoundingBox(this.makeBoundingBox());
|
||||||
|
// sync to clients
|
||||||
|
if (!level().isClientSide) {
|
||||||
|
this.entityData.set(STRUCTURE_TAG, this.structure.save());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSyncedDataUpdated(@NotNull EntityDataAccessor<?> key) {
|
||||||
|
super.onSyncedDataUpdated(key);
|
||||||
|
if (STRUCTURE_TAG.equals(key)) {
|
||||||
|
CompoundTag tag = this.entityData.get(STRUCTURE_TAG);
|
||||||
|
this.applyStructureTag(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readAdditionalSaveData(CompoundTag tag) {
|
||||||
|
if (tag.contains("RocketStructure")) {
|
||||||
|
CompoundTag rocketTag = tag.getCompound("RocketStructure");
|
||||||
|
structure.load(rocketTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addAdditionalSaveData(CompoundTag tag) {
|
||||||
|
tag.put("RocketStructure", structure.save());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNoGravity() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeCollidedWith() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPushedByFluid(@NotNull FluidType type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override @NotNull
|
||||||
|
protected AABB makeBoundingBox() {
|
||||||
|
if (structure == null) {
|
||||||
|
double half = 0.5;
|
||||||
|
return new AABB(
|
||||||
|
getX() - half, getY() - half + 0.5, getZ() - half,
|
||||||
|
getX() + half, getY() + half + 0.5, getZ() + half
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return computeWorldAABBFromStructure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override @NotNull
|
||||||
|
public AABB getBoundingBoxForCulling() {
|
||||||
|
if (structure == null)
|
||||||
|
return super.getBoundingBoxForCulling();
|
||||||
|
return computeWorldAABBFromStructure();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override @NotNull
|
||||||
|
public EntityDimensions getDimensions(@NotNull Pose pose) {
|
||||||
|
// Example: dynamic size you already compute for your rocket
|
||||||
|
EntityDimensions base = EntityDimensions.scalable(1, 1);
|
||||||
|
|
||||||
|
// Put “eyes” near the top (1 block below top here)
|
||||||
|
return base.withEyeHeight(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
if (!level().isClientSide) {
|
||||||
|
// Simple upward movement
|
||||||
|
setDeltaMovement(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
move(MoverType.SELF, getDeltaMovement());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeSpawnData(RegistryFriendlyByteBuf buf) {
|
||||||
|
buf.writeNbt(structure.save());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readSpawnData(RegistryFriendlyByteBuf buf) {
|
||||||
|
CompoundTag tag = buf.readNbt();
|
||||||
|
if (tag != null) {
|
||||||
|
structure.load(tag);
|
||||||
|
refreshDimensions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyStructureTag(CompoundTag structureTag) {
|
||||||
|
this.structure.load(structureTag);
|
||||||
|
this.refreshDimensions(); // if your hitbox/eye depends on structure
|
||||||
|
}
|
||||||
|
|
||||||
|
private AABB computeWorldAABBFromStructure() {
|
||||||
|
RocketStructure.Extents e = structure.computeExtents();
|
||||||
|
AABB local = e.toLocalAABB(); // [min, max+1] in local structure coords
|
||||||
|
|
||||||
|
return local.move(getX(), getY(), getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hurt(DamageSource source, float amount) {
|
||||||
|
return super.hurt(source, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPickable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package net.xevianlight.aphelion.entites.vehicles;
|
||||||
|
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||||
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.xevianlight.aphelion.util.RocketStructure;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class RocketRenderer extends EntityRenderer<RocketEntity> {
|
||||||
|
|
||||||
|
private final BlockRenderDispatcher blockRenderer;
|
||||||
|
|
||||||
|
public RocketRenderer(EntityRendererProvider.Context ctx) {
|
||||||
|
super(ctx);
|
||||||
|
this.blockRenderer = ctx.getBlockRenderDispatcher(); // ✅ correct source
|
||||||
|
this.shadowRadius = 0.8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(@NotNull RocketEntity entity,
|
||||||
|
float entityYaw,
|
||||||
|
float partialTicks,
|
||||||
|
PoseStack poseStack,
|
||||||
|
@NotNull MultiBufferSource buffers,
|
||||||
|
int packedLight) {
|
||||||
|
|
||||||
|
RocketStructure s = entity.getStructure();
|
||||||
|
|
||||||
|
for (int i = 0; i < s.size(); i++) {
|
||||||
|
int p = s.packedPosAt(i);
|
||||||
|
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.translate(
|
||||||
|
RocketStructure.unpackX(p) - 0.5d,
|
||||||
|
RocketStructure.unpackY(p),
|
||||||
|
RocketStructure.unpackZ(p) - 0.5d
|
||||||
|
);
|
||||||
|
|
||||||
|
blockRenderer.renderSingleBlock(
|
||||||
|
s.stateAt(i),
|
||||||
|
poseStack,
|
||||||
|
buffers,
|
||||||
|
packedLight,
|
||||||
|
OverlayTexture.NO_OVERLAY
|
||||||
|
);
|
||||||
|
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
super.render(entity, entityYaw, partialTicks, poseStack, buffers, packedLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceLocation getTextureLocation(RocketEntity entity) {
|
||||||
|
// Not used by block rendering, but required.
|
||||||
|
return ResourceLocation.withDefaultNamespace("textures/misc/white.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import net.minecraft.world.level.dimension.DimensionType;
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
|
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
|
||||||
import net.xevianlight.aphelion.client.dimension.DimensionSkyEffects;
|
import net.xevianlight.aphelion.client.dimension.DimensionSkyEffects;
|
||||||
|
import net.xevianlight.aphelion.client.dimension.SpaceSkyEffects;
|
||||||
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;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
@@ -18,7 +19,7 @@ public abstract class DimensionSpecialEffectsMixin {
|
|||||||
ResourceLocation effectsId = type.effectsLocation();
|
ResourceLocation effectsId = type.effectsLocation();
|
||||||
|
|
||||||
if (DimensionRendererCache.RENDERERS.containsKey(effectsId)) {
|
if (DimensionRendererCache.RENDERERS.containsKey(effectsId)) {
|
||||||
cir.setReturnValue(new DimensionSkyEffects(effectsId));
|
cir.setReturnValue(new SpaceSkyEffects(effectsId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package net.xevianlight.aphelion.planet;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.mojang.serialization.JsonOps;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.packs.resources.ResourceManager;
|
||||||
|
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
|
||||||
|
import net.minecraft.util.GsonHelper;
|
||||||
|
import net.minecraft.util.profiling.ProfilerFiller;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.client.dimension.DimensionRenderer;
|
||||||
|
import net.xevianlight.aphelion.util.Constants;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AphelionPlanetJSONLoader extends SimpleJsonResourceReloadListener {
|
||||||
|
|
||||||
|
public AphelionPlanetJSONLoader() {
|
||||||
|
super(Constants.GSON, "planet");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void apply(Map<ResourceLocation, JsonElement> object,
|
||||||
|
ResourceManager resourceManager,
|
||||||
|
ProfilerFiller profiler) {
|
||||||
|
|
||||||
|
Map<ResourceLocation, Planet> planets = new HashMap<>();
|
||||||
|
object.forEach((key, value) -> {
|
||||||
|
JsonObject json = GsonHelper.convertToJsonObject(value, "planet");
|
||||||
|
Planet planet = Planet.CODEC.parse(JsonOps.INSTANCE, json).getOrThrow();
|
||||||
|
|
||||||
|
// IMPORTANT: use the *resource id* of the json as the lookup key
|
||||||
|
// so "effects": "aphelion:space" maps to space.json automatically.
|
||||||
|
planets.put(key, planet);
|
||||||
|
});
|
||||||
|
|
||||||
|
Aphelion.LOGGER.info("Loaded planets " + planets);
|
||||||
|
|
||||||
|
PlanetCache.registerPlanets(planets);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/java/net/xevianlight/aphelion/planet/Planet.java
Normal file
21
src/main/java/net/xevianlight/aphelion/planet/Planet.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package net.xevianlight.aphelion.planet;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.xevianlight.aphelion.util.registries.ModRegistries;
|
||||||
|
|
||||||
|
public record Planet(
|
||||||
|
ResourceKey<Level> dimension,
|
||||||
|
double orbitDistance,
|
||||||
|
ResourceKey<StarSystem> system
|
||||||
|
) {
|
||||||
|
public static final Codec<Planet> CODEC = RecordCodecBuilder.create(inst -> inst.group(
|
||||||
|
ResourceKey.codec(Registries.DIMENSION).fieldOf("dimension").forGetter(Planet::dimension),
|
||||||
|
Codec.DOUBLE.fieldOf("orbit_distance").forGetter(Planet::orbitDistance),
|
||||||
|
ResourceKey.codec(ModRegistries.STAR_SYSTEM).fieldOf("star_system").forGetter(Planet::system)
|
||||||
|
|
||||||
|
).apply(inst, Planet::new));
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package net.xevianlight.aphelion.planet;
|
||||||
|
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.util.registries.ModRegistries;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class PlanetCache {
|
||||||
|
|
||||||
|
public static final Map<ResourceLocation, Planet> PLANETS = new HashMap<>();
|
||||||
|
public static final Map<ResourceKey<Level>, ResourceLocation> PLANET_BY_DIMENSION = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Planet DEFAULT = new Planet(
|
||||||
|
ResourceKey.create(Registries.DIMENSION, ResourceLocation.withDefaultNamespace("overworld")),
|
||||||
|
1,
|
||||||
|
ResourceKey.create(ModRegistries.STAR_SYSTEM, Aphelion.id("sol"))
|
||||||
|
);
|
||||||
|
|
||||||
|
public static void registerPlanets(Map<ResourceLocation, Planet> planets) {
|
||||||
|
PLANETS.clear();
|
||||||
|
PLANET_BY_DIMENSION.clear();
|
||||||
|
|
||||||
|
PLANETS.putAll(planets);
|
||||||
|
|
||||||
|
planets.forEach((planetId, planet) -> {
|
||||||
|
var dim = planet.dimension();
|
||||||
|
var prev = PLANET_BY_DIMENSION.put(dim, planetId);
|
||||||
|
if (prev != null) {
|
||||||
|
Aphelion.LOGGER.warn(
|
||||||
|
"Dimension {} is claimed by multiple planets: {} and {}. Keeping latest: {}",
|
||||||
|
dim.location(), prev, planetId, planetId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Aphelion.LOGGER.info("Loaded {} planets; {} dimension mappings",
|
||||||
|
PLANETS.size(), PLANET_BY_DIMENSION.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Planet getOrDefault(ResourceLocation id) {
|
||||||
|
return PLANETS.getOrDefault(id, DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Planet getByDimensionOrNull(ResourceKey<Level> dimension) {
|
||||||
|
ResourceLocation planetId = PLANET_BY_DIMENSION.get(dimension);
|
||||||
|
return planetId == null ? null : PLANETS.get(planetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package net.xevianlight.aphelion.planet;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
public record StarSystem(
|
||||||
|
int temp
|
||||||
|
) {
|
||||||
|
public static final Codec<StarSystem> CODEC = RecordCodecBuilder.create(inst -> inst.group(
|
||||||
|
Codec.INT.fieldOf("dimension").forGetter(StarSystem::temp)
|
||||||
|
).apply(inst, StarSystem::new));
|
||||||
|
}
|
||||||
138
src/main/java/net/xevianlight/aphelion/util/RocketStructure.java
Normal file
138
src/main/java/net/xevianlight/aphelion/util/RocketStructure.java
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package net.xevianlight.aphelion.util;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
import net.minecraft.nbt.*;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class RocketStructure {
|
||||||
|
|
||||||
|
|
||||||
|
private final List<BlockState> palette = new ArrayList<>();
|
||||||
|
private final IntList packedPositions = new IntArrayList();
|
||||||
|
private final IntList paletteIndices = new IntArrayList();
|
||||||
|
|
||||||
|
public RocketStructure(Builder builder) {
|
||||||
|
builder.build(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Builder {
|
||||||
|
void build(RocketStructure s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() { return packedPositions.size(); }
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
palette.clear();
|
||||||
|
packedPositions.clear();
|
||||||
|
paletteIndices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(int x, int y, int z, BlockState state) {
|
||||||
|
if (state == Blocks.AIR.defaultBlockState()) return;
|
||||||
|
int idx = palette.indexOf(state);
|
||||||
|
if (idx < 0) {
|
||||||
|
palette.add(state);
|
||||||
|
idx = palette.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
packedPositions.add(packPos(x, y, z));
|
||||||
|
paletteIndices.add(idx); // ← REQUIRED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BlockState stateAt(int i) { return palette.get(paletteIndices.getInt(i)); }
|
||||||
|
public int packedPosAt(int i) { return packedPositions.getInt(i); }
|
||||||
|
|
||||||
|
public CompoundTag save() {
|
||||||
|
CompoundTag tag = new CompoundTag();
|
||||||
|
|
||||||
|
// palette
|
||||||
|
ListTag pal = new ListTag();
|
||||||
|
for (BlockState st : palette) {
|
||||||
|
pal.add(BlockState.CODEC.encodeStart(NbtOps.INSTANCE, st)
|
||||||
|
.getOrThrow());
|
||||||
|
}
|
||||||
|
tag.put("palette", pal);
|
||||||
|
|
||||||
|
// blocks
|
||||||
|
IntArrayTag posArr = new IntArrayTag(packedPositions.toIntArray());
|
||||||
|
IntArrayTag idxArr = new IntArrayTag(paletteIndices.toIntArray());
|
||||||
|
tag.put("pos", posArr);
|
||||||
|
tag.put("idx", idxArr);
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(CompoundTag tag) {
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// palette
|
||||||
|
ListTag pal = tag.getList("palette", Tag.TAG_COMPOUND);
|
||||||
|
for (int i = 0; i < pal.size(); i++) {
|
||||||
|
Tag stTag = pal.get(i);
|
||||||
|
BlockState st = BlockState.CODEC.parse(NbtOps.INSTANCE, stTag)
|
||||||
|
.getOrThrow();
|
||||||
|
palette.add(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
// blocks
|
||||||
|
int[] pos = tag.getIntArray("pos");
|
||||||
|
int[] idx = tag.getIntArray("idx");
|
||||||
|
|
||||||
|
for (int i = 0; i < pos.length; i++) {
|
||||||
|
packedPositions.add(pos[i]);
|
||||||
|
paletteIndices.add(idx[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int packPos (int x, int y, int z) {
|
||||||
|
return (x & 0xFF) | ((y & 0xFF) << 8) | ((z & 0xFF) << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int unpackX (int p) { return (byte) (p & 0xFF); }
|
||||||
|
public static int unpackY (int p) { return (byte) (( p >> 8) & 0xFF); }
|
||||||
|
public static int unpackZ (int p) { return (byte) (( p >> 16) & 0xFF); }
|
||||||
|
|
||||||
|
public record Extents(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
|
||||||
|
public int sizeX() { return maxX - minX + 1; }
|
||||||
|
public int sizeY() { return maxY - minY + 1; }
|
||||||
|
public int sizeZ() { return maxZ - minZ + 1; }
|
||||||
|
|
||||||
|
public AABB toLocalAABB() {
|
||||||
|
return new AABB(minX - 0.5, minY, minZ - 0.5, maxX + 0.5, maxY + 1, maxZ + 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Extents computeExtents() {
|
||||||
|
if (size() == 0) {
|
||||||
|
return new Extents(0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, minZ = Integer.MAX_VALUE;
|
||||||
|
int maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE, maxZ = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
int p = packedPosAt(i);
|
||||||
|
int x = unpackX(p);
|
||||||
|
int y = unpackY(p);
|
||||||
|
int z = unpackZ(p);
|
||||||
|
|
||||||
|
if (x < minX) minX = x;
|
||||||
|
if (y < minY) minY = y;
|
||||||
|
if (z < minZ) minZ = z;
|
||||||
|
|
||||||
|
if (x > maxX) maxX = x;
|
||||||
|
if (y > maxY) maxY = y;
|
||||||
|
if (z > maxZ) maxZ = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Extents(minX, minY, minZ, maxX, maxY, maxZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package net.xevianlight.aphelion.util.registries;
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.planet.Planet;
|
||||||
|
import net.xevianlight.aphelion.planet.StarSystem;
|
||||||
|
|
||||||
|
public class ModRegistries {
|
||||||
|
public static final ResourceKey<Registry<StarSystem>> STAR_SYSTEM = createRegistryKey("star_system");
|
||||||
|
public static final ResourceKey<Registry<Planet>> PLANET = createRegistryKey("planet");
|
||||||
|
|
||||||
|
private static <T> ResourceKey<Registry<T>> createRegistryKey(String name) {
|
||||||
|
return ResourceKey.createRegistryKey(Aphelion.id(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,11 +33,14 @@
|
|||||||
"command.aphelion.station.orbit.get": "Station (%s, %s)'s orbit is assigned to %s",
|
"command.aphelion.station.orbit.get": "Station (%s, %s)'s orbit is assigned to %s",
|
||||||
"command.aphelion.station.orbit.get.unassigned": "Station (%s, %s)'s orbit is not assigned",
|
"command.aphelion.station.orbit.get.unassigned": "Station (%s, %s)'s orbit is not assigned",
|
||||||
"command.aphelion.station.orbit.cleared": "Cleared station (%s, %s)'s orbit",
|
"command.aphelion.station.orbit.cleared": "Cleared station (%s, %s)'s orbit",
|
||||||
"command.aphelion.station.orbit.clearall": "Cleared all station orbits",
|
"command.aphelion.station.orbit.clear_all": "Cleared all station orbits",
|
||||||
"command.aphelion.station.orbit.overwriteall": "Set all existing station orbits with %s (unassigned stations were not affected)",
|
"command.aphelion.station.orbit.overwrite_all": "Set all existing station orbits with %s (unassigned stations were not affected)",
|
||||||
"command.aphelion.station.orbit.debug.posToKey": "Key of station (%s, %s) is %s",
|
"command.aphelion.station.orbit.debug.posToKey": "Key of station (%s, %s) is %s",
|
||||||
"command.aphelion.station.orbit.debug.keyToPos": "Key %s belongs to station %s",
|
"command.aphelion.station.orbit.debug.keyToPos": "Key %s belongs to station %s",
|
||||||
"command.aphelion.station.teleport.success": "Teleported %s to station %s, id: %s",
|
"command.aphelion.station.teleport.success": "Teleported %s to station %s, id: %s",
|
||||||
"command.aphelion.station.teleport.failure": "Failed to teleport, entity is null",
|
"command.aphelion.station.teleport.failure": "Failed to teleport, entity is null",
|
||||||
"command.aphelion.station.orbit.debug.getPartition": "Partition of %s, %s is %s"
|
"command.aphelion.station.teleport.failure.invalid_level": "Failed to teleport, target level is null",
|
||||||
|
"command.aphelion.station.orbit.debug.getPartition": "Partition of %s, %s is %s",
|
||||||
|
"command.aphelion.rocket.entity_invalid": "Entity is not a valid rocket",
|
||||||
|
"command.aphelion.rocket.spawn.success": "Summoned new rocket"
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/main/resources/data/aphelion/planet/overworld.json
Normal file
5
src/main/resources/data/aphelion/planet/overworld.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"dimension": "minecraft:overworld",
|
||||||
|
"orbit_distance": 1,
|
||||||
|
"star_system": "aphelon:sol"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user