mirror of
https://github.com/XevianLight/Aphelion.git
synced 2026-05-11 01:50:56 +01:00
Server side partition syncing and packets
This commit is contained in:
@@ -62,7 +62,9 @@ public class Aphelion {
|
|||||||
NeoForge.EVENT_BUS.register(this);
|
NeoForge.EVENT_BUS.register(this);
|
||||||
|
|
||||||
// Register the item to a creative tab
|
// Register the item to a creative tab
|
||||||
modEventBus.addListener(this::addCreative);
|
MOD_BUS.addListener(this::addCreative);
|
||||||
|
|
||||||
|
// MOD_BUS.addListener(this::registerCommands);
|
||||||
|
|
||||||
// Register our mod's ModConfigSpec so that FML can create and load the config file for us
|
// Register our mod's ModConfigSpec so that FML can create and load the config file for us
|
||||||
modContainer.registerConfig(ModConfig.Type.COMMON, AphelionConfig.SPEC);
|
modContainer.registerConfig(ModConfig.Type.COMMON, AphelionConfig.SPEC);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import net.xevianlight.aphelion.Aphelion;
|
|||||||
import net.xevianlight.aphelion.client.dimension.DimensionRenderer;
|
import net.xevianlight.aphelion.client.dimension.DimensionRenderer;
|
||||||
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
|
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
|
||||||
import net.xevianlight.aphelion.client.dimension.SpaceSkyEffects;
|
import net.xevianlight.aphelion.client.dimension.SpaceSkyEffects;
|
||||||
|
import net.xevianlight.aphelion.core.space.SpacePartitionSavedData;
|
||||||
|
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
||||||
|
|
||||||
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
|
@EventBusSubscriber(modid = Aphelion.MOD_ID, value = Dist.CLIENT)
|
||||||
public class AphelionDebugOverlay {
|
public class AphelionDebugOverlay {
|
||||||
@@ -35,10 +37,14 @@ public class AphelionDebugOverlay {
|
|||||||
+ ", thickFog=" + r.hasThickFog()
|
+ ", thickFog=" + r.hasThickFog()
|
||||||
+ ", fog=" + r.hasFog());
|
+ ", fog=" + r.hasFog());
|
||||||
|
|
||||||
|
int x = SpacePartitionHelper.get(Math.floor(mc.player.position().x));
|
||||||
|
int z = SpacePartitionHelper.get(Math.floor(mc.player.position().z));
|
||||||
|
|
||||||
// Left side of F3
|
// Left side of F3
|
||||||
event.getLeft().add("");
|
event.getLeft().add("");
|
||||||
event.getLeft().add("Aphelion:");
|
event.getLeft().add("Aphelion:");
|
||||||
event.getLeft().add(" Orbit: " + orbitId);
|
event.getLeft().add(" Orbit: " + orbitId);
|
||||||
event.getLeft().add(" Sky: " + rendererSummary);
|
// event.getLeft().add(" Sky: " + rendererSummary);
|
||||||
|
event.getLeft().add(" Station: " + x + " " + z + " ID: " + SpacePartitionSavedData.pack(x,z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package net.xevianlight.aphelion.client;
|
||||||
|
|
||||||
|
import net.xevianlight.aphelion.network.packet.PartitionData;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public final class PartitionClientState {
|
||||||
|
private static volatile PartitionData last = null;
|
||||||
|
|
||||||
|
public static void set(PartitionData d) { last = d; }
|
||||||
|
|
||||||
|
public static Optional<PartitionData> get() {
|
||||||
|
return Optional.ofNullable(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String idOrUnknown() {
|
||||||
|
return last != null ? last.id() : "unknown";
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// public static int pxOr(int fallback) {
|
||||||
|
// return last != null ? last.px() : fallback;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static int pyOr(int fallback) {
|
||||||
|
// return last != null ? last.py() : fallback;
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ public record DimensionRenderer(
|
|||||||
int sunriseColor,
|
int sunriseColor,
|
||||||
int sunriseAngle,
|
int sunriseAngle,
|
||||||
boolean renderInRain,
|
boolean renderInRain,
|
||||||
boolean renderVoidFog,
|
|
||||||
double horizonHeight,
|
double horizonHeight,
|
||||||
float clearColorScale
|
float clearColorScale
|
||||||
) {
|
) {
|
||||||
@@ -32,7 +31,6 @@ public record DimensionRenderer(
|
|||||||
Codec.INT.fieldOf("sunrise_color").forGetter(DimensionRenderer::sunriseColor),
|
Codec.INT.fieldOf("sunrise_color").forGetter(DimensionRenderer::sunriseColor),
|
||||||
Codec.INT.fieldOf("sunrise_angle").forGetter(DimensionRenderer::sunriseAngle),
|
Codec.INT.fieldOf("sunrise_angle").forGetter(DimensionRenderer::sunriseAngle),
|
||||||
Codec.BOOL.fieldOf("render_in_rain").forGetter(DimensionRenderer::renderInRain),
|
Codec.BOOL.fieldOf("render_in_rain").forGetter(DimensionRenderer::renderInRain),
|
||||||
Codec.BOOL.fieldOf("render_void_fog").forGetter(DimensionRenderer::renderVoidFog),
|
|
||||||
Codec.DOUBLE.fieldOf("horizon_height").forGetter(DimensionRenderer::horizonHeight),
|
Codec.DOUBLE.fieldOf("horizon_height").forGetter(DimensionRenderer::horizonHeight),
|
||||||
Codec.FLOAT.fieldOf("clear_color_scale").forGetter(DimensionRenderer::clearColorScale)
|
Codec.FLOAT.fieldOf("clear_color_scale").forGetter(DimensionRenderer::clearColorScale)
|
||||||
).apply(inst, DimensionRenderer::new));
|
).apply(inst, DimensionRenderer::new));
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package net.xevianlight.aphelion.client.dimension;
|
package net.xevianlight.aphelion.client.dimension;
|
||||||
|
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.resources.ResourceKey;
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -11,6 +13,20 @@ public final class DimensionRendererCache {
|
|||||||
|
|
||||||
public static final Map<ResourceLocation, DimensionRenderer> RENDERERS = new HashMap<>();
|
public static final Map<ResourceLocation, DimensionRenderer> RENDERERS = new HashMap<>();
|
||||||
|
|
||||||
|
public static final DimensionRenderer DEFAULT = new DimensionRenderer(
|
||||||
|
ResourceKey.create(Registries.DIMENSION, ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space")),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
14180147,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
63,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
public static void registerPlanetRenderers(Map<ResourceLocation, DimensionRenderer> renderers) {
|
public static void registerPlanetRenderers(Map<ResourceLocation, DimensionRenderer> renderers) {
|
||||||
RENDERERS.clear();
|
RENDERERS.clear();
|
||||||
RENDERERS.putAll(renderers);
|
RENDERERS.putAll(renderers);
|
||||||
@@ -18,6 +34,6 @@ public final class DimensionRendererCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static DimensionRenderer getOrDefault(ResourceLocation id) {
|
public static DimensionRenderer getOrDefault(ResourceLocation id) {
|
||||||
return RENDERERS.getOrDefault(id, null);
|
return RENDERERS.getOrDefault(id, DEFAULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
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.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
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.core.space.SpacePartitionSavedData;
|
||||||
|
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
|
||||||
public class SpaceSkyEffects extends DimensionSpecialEffects {
|
public class SpaceSkyEffects extends DimensionSpecialEffects {
|
||||||
@@ -42,6 +48,7 @@ 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 = orbitForPos(net.minecraft.client.Minecraft.getInstance()
|
||||||
.gameRenderer.getMainCamera().getPosition());
|
.gameRenderer.getMainCamera().getPosition());
|
||||||
|
|
||||||
@@ -49,11 +56,19 @@ public class SpaceSkyEffects extends DimensionSpecialEffects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ResourceLocation orbitForPos(Vec3 pos) {
|
public static ResourceLocation orbitForPos(Vec3 pos) {
|
||||||
double r = Math.sqrt(pos.x * pos.x + pos.z * pos.z);
|
|
||||||
|
|
||||||
if (r < 100) return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/earth");
|
int x = SpacePartitionHelper.get(pos.x);
|
||||||
if (r < 200) return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/mars");
|
int z = SpacePartitionHelper.get(pos.z);
|
||||||
if (r < 300) return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/venus");
|
|
||||||
|
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");
|
return ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "orbit/default");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,285 @@
|
|||||||
|
package net.xevianlight.aphelion.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.Command;
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.LongArgumentType;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.Commands;
|
||||||
|
import net.minecraft.commands.arguments.*;
|
||||||
|
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.network.chat.ClickEvent;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.ComponentUtils;
|
||||||
|
import net.minecraft.network.chat.HoverEvent;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.entity.RelativeMovement;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.core.space.SpacePartitionSavedData;
|
||||||
|
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
public class AphelionCommand {
|
||||||
|
|
||||||
|
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||||
|
dispatcher.register(Commands.literal("aphelion")
|
||||||
|
.requires(source -> source.hasPermission(3))
|
||||||
|
.then(Commands.literal("station")
|
||||||
|
.then(Commands.literal("orbit")
|
||||||
|
.then(Commands.literal("set")
|
||||||
|
.then(Commands.argument("pos", ColumnPosArgument.columnPos())
|
||||||
|
.then(Commands.argument("orbit", ResourceLocationArgument.id())
|
||||||
|
.executes(context -> {
|
||||||
|
int x = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context, "pos").x());
|
||||||
|
int z = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context, "pos").z());
|
||||||
|
ResourceLocation orbit = ResourceLocationArgument.getId(context, "orbit");
|
||||||
|
|
||||||
|
ServerLevel level = context.getSource().getLevel();
|
||||||
|
SpacePartitionSavedData.get(level).setOrbitForPartition(x, z, orbit);
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.set", x, z, orbit.toString()),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("all")
|
||||||
|
.then(Commands.argument("orbit", ResourceLocationArgument.id())
|
||||||
|
.executes(context -> {
|
||||||
|
ResourceLocation orbit = ResourceLocationArgument.getId(context, "orbit");
|
||||||
|
|
||||||
|
ServerLevel level = context.getSource().getLevel();
|
||||||
|
|
||||||
|
SpacePartitionSavedData.get(level).overwriteAllExistingOrbits(orbit);
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.overwriteall", orbit.toString()),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("get")
|
||||||
|
.then(Commands.argument("pos", ColumnPosArgument.columnPos())
|
||||||
|
.executes(context -> {
|
||||||
|
int x = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context, "pos").x());
|
||||||
|
int z = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context, "pos").z());
|
||||||
|
|
||||||
|
ServerLevel level = context.getSource().getLevel();
|
||||||
|
ResourceLocation orbit = SpacePartitionSavedData.get(level).getOrbitForPartition(x, z);
|
||||||
|
|
||||||
|
if (orbit != null) {
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.get", x, z, orbit.toString()),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.get.unassigned", x, z),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("clear")
|
||||||
|
.then(Commands.argument("pos", ColumnPosArgument.columnPos())
|
||||||
|
.executes(context -> {
|
||||||
|
int x = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context, "pos").x());
|
||||||
|
int z = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context, "pos").z());
|
||||||
|
|
||||||
|
ServerLevel level = context.getSource().getLevel();
|
||||||
|
|
||||||
|
boolean success = SpacePartitionSavedData.get(level).clearOrbitForPartition(x, z);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.cleared", x, z),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(Commands.literal("all")
|
||||||
|
.executes(context -> {
|
||||||
|
ServerLevel level = context.getSource().getLevel();
|
||||||
|
|
||||||
|
SpacePartitionSavedData.get(level).clearAllOrbits();
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.clearall"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("debug")
|
||||||
|
.then(Commands.literal("posToKey")
|
||||||
|
.then(Commands.argument("pos", ColumnPosArgument.columnPos())
|
||||||
|
.executes(context -> {
|
||||||
|
ServerLevel level = context.getSource().getLevel();
|
||||||
|
|
||||||
|
int x = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context,"pos").x());
|
||||||
|
int z = SpacePartitionHelper.get(ColumnPosArgument.getColumnPos(context,"pos").z());
|
||||||
|
|
||||||
|
long key = SpacePartitionSavedData.pack(x,z);
|
||||||
|
|
||||||
|
Component clickableOutput = Component.literal(String.valueOf(key))
|
||||||
|
.withStyle(style -> style
|
||||||
|
.withClickEvent(new ClickEvent(
|
||||||
|
ClickEvent.Action.COPY_TO_CLIPBOARD,
|
||||||
|
String.valueOf(key)
|
||||||
|
))
|
||||||
|
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click")))
|
||||||
|
.withColor(ChatFormatting.AQUA)
|
||||||
|
);
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.debug.posToKey", x, z, clickableOutput),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("keyToPos")
|
||||||
|
.then(Commands.argument("key", LongArgumentType.longArg(0, Long.MAX_VALUE))
|
||||||
|
.executes(context -> {
|
||||||
|
ServerLevel level = context.getSource().getLevel();
|
||||||
|
|
||||||
|
|
||||||
|
long key = LongArgumentType.getLong(context,"key");
|
||||||
|
|
||||||
|
int x = SpacePartitionSavedData.unpackX(key);
|
||||||
|
int z = SpacePartitionSavedData.unpackZ(key);
|
||||||
|
|
||||||
|
String stationCoord = x + " " + z;
|
||||||
|
|
||||||
|
Component clickableOutput = ComponentUtils.wrapInSquareBrackets(Component.literal(stationCoord))
|
||||||
|
.withStyle(style -> style
|
||||||
|
.withClickEvent(new ClickEvent(
|
||||||
|
ClickEvent.Action.COPY_TO_CLIPBOARD,
|
||||||
|
stationCoord
|
||||||
|
))
|
||||||
|
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click")))
|
||||||
|
.withColor(ChatFormatting.GREEN)
|
||||||
|
);
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.debug.keyToPos", key, clickableOutput),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("getPartition")
|
||||||
|
.then(Commands.argument("pos", ColumnPosArgument.columnPos())
|
||||||
|
.executes(context -> {
|
||||||
|
|
||||||
|
int x = ColumnPosArgument.getColumnPos(context, "pos").x();
|
||||||
|
int z = ColumnPosArgument.getColumnPos(context, "pos").z();
|
||||||
|
|
||||||
|
String stationCoord = SpacePartitionHelper.get(x) + " " + SpacePartitionHelper.get(z);
|
||||||
|
|
||||||
|
Component clickableOutput = ComponentUtils.wrapInSquareBrackets(Component.literal(stationCoord))
|
||||||
|
.withStyle(style -> style
|
||||||
|
.withClickEvent(new ClickEvent(
|
||||||
|
ClickEvent.Action.COPY_TO_CLIPBOARD,
|
||||||
|
stationCoord
|
||||||
|
))
|
||||||
|
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click")))
|
||||||
|
.withColor(ChatFormatting.GREEN)
|
||||||
|
);
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.orbit.debug.getPartition", x, z, clickableOutput),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("tp")
|
||||||
|
.then(Commands.argument("x", IntegerArgumentType.integer())
|
||||||
|
.then(Commands.argument("z", IntegerArgumentType.integer())
|
||||||
|
.executes(context -> {
|
||||||
|
var player = context.getSource().getEntity();
|
||||||
|
|
||||||
|
double x = (double) IntegerArgumentType.getInteger(context, "x");
|
||||||
|
double z = (double) IntegerArgumentType.getInteger(context, "z");
|
||||||
|
|
||||||
|
int destX = (int) Math.floor(x * SpacePartitionHelper.SIZE) + (SpacePartitionHelper.SIZE / 2);
|
||||||
|
int destZ = (int) Math.floor(z * SpacePartitionHelper.SIZE) + (SpacePartitionHelper.SIZE / 2);
|
||||||
|
|
||||||
|
String stationCoord = x + ", " + z;
|
||||||
|
|
||||||
|
long key = SpacePartitionSavedData.pack((int) x, (int) z);
|
||||||
|
|
||||||
|
Component clickablePos = ComponentUtils.wrapInSquareBrackets(Component.literal(stationCoord))
|
||||||
|
.withStyle(style -> style
|
||||||
|
.withClickEvent(new ClickEvent(
|
||||||
|
ClickEvent.Action.COPY_TO_CLIPBOARD,
|
||||||
|
stationCoord
|
||||||
|
))
|
||||||
|
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click")))
|
||||||
|
.withColor(ChatFormatting.GREEN)
|
||||||
|
);
|
||||||
|
|
||||||
|
Component clickableId = Component.literal(String.valueOf(key))
|
||||||
|
.withStyle(style -> style
|
||||||
|
.withClickEvent(new ClickEvent(
|
||||||
|
ClickEvent.Action.COPY_TO_CLIPBOARD,
|
||||||
|
String.valueOf(key)
|
||||||
|
))
|
||||||
|
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click")))
|
||||||
|
.withColor(ChatFormatting.AQUA)
|
||||||
|
);
|
||||||
|
|
||||||
|
ServerLevel space = player.getServer().getLevel(ResourceKey.create(Registries.DIMENSION, ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space")));
|
||||||
|
|
||||||
|
if (player != null) {
|
||||||
|
player.teleportTo(space, destX, player.position().y, destZ, EnumSet.noneOf(RelativeMovement.class), player.getYRot(), player.getXRot());
|
||||||
|
|
||||||
|
context.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("aphelion.command.station.teleport.success", player.getDisplayName(), clickablePos, clickableId),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.getSource().sendFailure(
|
||||||
|
Component.translatable("aphelion.command.station.teleport.failure")
|
||||||
|
);
|
||||||
|
|
||||||
|
return Command.SINGLE_SUCCESS;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package net.xevianlight.aphelion.commands;
|
||||||
|
|
||||||
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
|
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
|
||||||
|
@EventBusSubscriber(modid = Aphelion.MOD_ID)
|
||||||
|
public class ModCommands {
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onRegisterCommands(RegisterCommandsEvent event) {
|
||||||
|
AphelionCommand.register(event.getDispatcher());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package net.xevianlight.aphelion.core.space;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.saveddata.SavedData;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class SpacePartitionSavedData extends SavedData {
|
||||||
|
|
||||||
|
private static final String NAME = "aphelion_station_partitions";
|
||||||
|
|
||||||
|
private final Long2ObjectMap<ResourceLocation> map = new Long2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
public static SpacePartitionSavedData create() {
|
||||||
|
return new SpacePartitionSavedData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpacePartitionSavedData load(CompoundTag tag, HolderLookup.Provider lookupProvider) {
|
||||||
|
SpacePartitionSavedData data = create();
|
||||||
|
|
||||||
|
ListTag entires = tag.getList("Entries", CompoundTag.TAG_COMPOUND);
|
||||||
|
for (int i = 0; i < entires.size(); i++) {
|
||||||
|
CompoundTag e = entires.getCompound(i);
|
||||||
|
long key = e.getLong("Key");
|
||||||
|
String orbit = e.getString("Orbit"); // "aphelion/mars"
|
||||||
|
ResourceLocation orbitRL = ResourceLocation.tryParse(orbit);
|
||||||
|
if (orbitRL != null)
|
||||||
|
data.map.put(key, orbitRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompoundTag save(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
|
ListTag entries = new ListTag();
|
||||||
|
|
||||||
|
map.long2ObjectEntrySet().forEach(entry -> {
|
||||||
|
CompoundTag e = new CompoundTag();
|
||||||
|
e.putLong("Key", entry.getLongKey());
|
||||||
|
e.putString("Orbit", entry.getValue().toString());
|
||||||
|
entries.add(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
tag.put("Entries", entries);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ResourceLocation getOrbitForPartition(int px, int pz) {
|
||||||
|
return map.get(pack(px, pz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrbitForPartition(int px, int pz, ResourceLocation orbit) {
|
||||||
|
long key = pack(px, pz);
|
||||||
|
ResourceLocation prev = map.get(key);
|
||||||
|
if (!orbit.equals(prev)) {
|
||||||
|
map.put(key, orbit);
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean clearOrbitForPartition(int px, int pz) {
|
||||||
|
long key = pack(px, pz);
|
||||||
|
ResourceLocation removed = map.remove(key);
|
||||||
|
if (removed != null) {
|
||||||
|
setDirty();;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearAllOrbits() {
|
||||||
|
if (!map.isEmpty()) {
|
||||||
|
map.clear();
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void overwriteAllExistingOrbits(ResourceLocation orbit) {
|
||||||
|
if (map.isEmpty()) return;
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
for (var entry : map.long2ObjectEntrySet()) {
|
||||||
|
if(!orbit.equals(entry.getValue())) {
|
||||||
|
entry.setValue(orbit);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpacePartitionSavedData get(ServerLevel level) {
|
||||||
|
return level.getDataStorage().computeIfAbsent(
|
||||||
|
new Factory<>(SpacePartitionSavedData::create, SpacePartitionSavedData::load),
|
||||||
|
NAME
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long pack(int px, int pz) {
|
||||||
|
return (((long) px) << 32) | (pz & 0xffffffffL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int unpackX(long key) {
|
||||||
|
return (int)(key >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int unpackZ(long key) {
|
||||||
|
return (int)key;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,10 +4,16 @@ import net.neoforged.bus.api.SubscribeEvent;
|
|||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||||
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
|
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
|
||||||
|
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
|
||||||
|
import net.neoforged.neoforge.network.handlers.ClientPayloadHandler;
|
||||||
|
import net.neoforged.neoforge.network.registration.HandlerThread;
|
||||||
|
import net.neoforged.neoforge.network.registration.PayloadRegistrar;
|
||||||
import net.xevianlight.aphelion.Aphelion;
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
import net.xevianlight.aphelion.block.entity.custom.ElectricArcFurnaceEntity;
|
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.core.init.ModBlockEntities;
|
import net.xevianlight.aphelion.core.init.ModBlockEntities;
|
||||||
|
import net.xevianlight.aphelion.network.ServerPayloadHandler;
|
||||||
|
import net.xevianlight.aphelion.network.packet.PartitionData;
|
||||||
|
|
||||||
@EventBusSubscriber(modid = Aphelion.MOD_ID)
|
@EventBusSubscriber(modid = Aphelion.MOD_ID)
|
||||||
public class ModBusEvents {
|
public class ModBusEvents {
|
||||||
@@ -17,4 +23,16 @@ public class ModBusEvents {
|
|||||||
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), ElectricArcFurnaceEntity::getItemHandler);
|
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), ElectricArcFurnaceEntity::getItemHandler);
|
||||||
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), ElectricArcFurnaceEntity::getEnergyStorage);
|
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, ModBlockEntities.ELECTRIC_ARC_FURNACE_ENTITY.get(), ElectricArcFurnaceEntity::getEnergyStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void registerPayloads(RegisterPayloadHandlersEvent event) {
|
||||||
|
final PayloadRegistrar registrar = event.registrar("1")
|
||||||
|
.executesOn(HandlerThread.MAIN);
|
||||||
|
|
||||||
|
registrar.playToClient(
|
||||||
|
PartitionData.TYPE,
|
||||||
|
PartitionData.STREAM_CODEC,
|
||||||
|
ServerPayloadHandler::handleDataOnMain);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,17 @@ package net.xevianlight.aphelion.mixins.common;
|
|||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.LevelHeightAccessor;
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.client.PartitionClientState;
|
||||||
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
|
import net.xevianlight.aphelion.client.dimension.DimensionRendererCache;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
@@ -16,6 +21,24 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||||||
@Mixin(ClientLevel.ClientLevelData.class)
|
@Mixin(ClientLevel.ClientLevelData.class)
|
||||||
public abstract class ClientLevelMixin {
|
public abstract class ClientLevelMixin {
|
||||||
|
|
||||||
|
|
||||||
|
private ClientLevel this$0;
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private ResourceLocation aphelion$getRenderKey() {
|
||||||
|
var mc = Minecraft.getInstance();
|
||||||
|
ClientLevel level = mc.level;
|
||||||
|
ResourceLocation key;
|
||||||
|
|
||||||
|
if (level.dimension() == ResourceKey.create(Registries.DIMENSION, ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "space"))) {
|
||||||
|
key = ResourceLocation.parse(PartitionClientState.idOrUnknown());
|
||||||
|
} else {
|
||||||
|
key = level.dimensionType().effectsLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "getHorizonHeight", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "getHorizonHeight", at = @At("HEAD"), cancellable = true)
|
||||||
private void aphelion$horizonHeight(LevelHeightAccessor level, CallbackInfoReturnable<Double> cir) {
|
private void aphelion$horizonHeight(LevelHeightAccessor level, CallbackInfoReturnable<Double> cir) {
|
||||||
var mc = Minecraft.getInstance();
|
var mc = Minecraft.getInstance();
|
||||||
@@ -23,7 +46,7 @@ public abstract class ClientLevelMixin {
|
|||||||
if (clientLevel == null) return;
|
if (clientLevel == null) return;
|
||||||
|
|
||||||
// effectsLocation is what your dimension JSON sets in "effects"
|
// effectsLocation is what your dimension JSON sets in "effects"
|
||||||
ResourceLocation effectsId = clientLevel.dimensionType().effectsLocation();
|
ResourceLocation effectsId = aphelion$getRenderKey();
|
||||||
|
|
||||||
var i = DimensionRendererCache.getOrDefault(effectsId);
|
var i = DimensionRendererCache.getOrDefault(effectsId);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package net.xevianlight.aphelion.network;
|
||||||
|
|
||||||
|
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
|
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
|
||||||
|
import net.neoforged.neoforge.event.tick.ServerTickEvent;
|
||||||
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.core.space.SpacePartitionSavedData;
|
||||||
|
import net.xevianlight.aphelion.network.packet.PartitionData;
|
||||||
|
import net.xevianlight.aphelion.util.SpacePartitionHelper;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@EventBusSubscriber(modid = Aphelion.MOD_ID)
|
||||||
|
public final class PartitionSync {
|
||||||
|
|
||||||
|
// send once right after join (safe: delayed to next server tick)
|
||||||
|
private static final Set<UUID> PENDING_JOIN_SEND = new HashSet<>();
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onLogin(PlayerEvent.PlayerLoggedInEvent e) {
|
||||||
|
if (e.getEntity() instanceof ServerPlayer sp) {
|
||||||
|
PENDING_JOIN_SEND.add(sp.getUUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final java.util.Map<UUID, PartitionData> LAST_SENT = new java.util.HashMap<>();
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onServerTick(ServerTickEvent.Post e) {
|
||||||
|
var server = e.getServer();
|
||||||
|
|
||||||
|
// Aphelion.LOGGER.info("WORKS!!!");
|
||||||
|
|
||||||
|
for (ServerPlayer sp : server.getPlayerList().getPlayers()) {
|
||||||
|
PartitionData now = computePartitionFor(sp); // your logic
|
||||||
|
PartitionData prev = LAST_SENT.get(sp.getUUID());
|
||||||
|
|
||||||
|
if (prev == null || !prev.equals(now)) {
|
||||||
|
PacketDistributor.sendToPlayer(sp, now);
|
||||||
|
LAST_SENT.put(sp.getUUID(), now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PartitionData computePartitionFor(ServerPlayer sp) {
|
||||||
|
// Example: convert player position to partition coords
|
||||||
|
int px = (int)Math.floor(sp.getX() / SpacePartitionHelper.SIZE);
|
||||||
|
int pz = (int)Math.floor(sp.getZ() / SpacePartitionHelper.SIZE);
|
||||||
|
|
||||||
|
var orbit = SpacePartitionSavedData.get(sp.serverLevel()).getOrbitForPartition(px, pz);
|
||||||
|
String orbitId = (orbit != null) ? orbit.toString() : "aphelion:orbit/default";
|
||||||
|
|
||||||
|
return new PartitionData(orbitId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package net.xevianlight.aphelion.network;
|
||||||
|
|
||||||
|
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||||
|
import net.xevianlight.aphelion.Aphelion;
|
||||||
|
import net.xevianlight.aphelion.client.PartitionClientState;
|
||||||
|
import net.xevianlight.aphelion.network.packet.PartitionData;
|
||||||
|
|
||||||
|
// Handle packets TO the client FROM the server
|
||||||
|
public class ServerPayloadHandler {
|
||||||
|
|
||||||
|
public static void handleDataOnMain(PartitionData data, IPayloadContext context) {
|
||||||
|
PartitionClientState.set(data);
|
||||||
|
Aphelion.LOGGER.info("Partition packet received! id={}", data.id());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
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 PartitionData (String id) implements CustomPacketPayload {
|
||||||
|
public static final Type<PartitionData> TYPE = new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(Aphelion.MOD_ID, "partition_data"));
|
||||||
|
|
||||||
|
public static final StreamCodec<ByteBuf, PartitionData> STREAM_CODEC = StreamCodec.composite(
|
||||||
|
ByteBufCodecs.STRING_UTF8,
|
||||||
|
PartitionData::id,
|
||||||
|
|
||||||
|
PartitionData::new
|
||||||
|
);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type<? extends CustomPacketPayload> type() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package net.xevianlight.aphelion.util;
|
||||||
|
|
||||||
|
public class SpacePartitionHelper {
|
||||||
|
|
||||||
|
public static final int SIZE = 16;
|
||||||
|
|
||||||
|
public static int get(double pos) {
|
||||||
|
return ceilDiv(pos, SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ceilDiv(double a, int b) {
|
||||||
|
return (int) Math.floor(a / b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -24,5 +24,18 @@
|
|||||||
"creativetab.aphelion.aphelion_blocks": "Aphelion Blocks",
|
"creativetab.aphelion.aphelion_blocks": "Aphelion Blocks",
|
||||||
|
|
||||||
"tag.item.c.ingots.steel": "Steel Ingots",
|
"tag.item.c.ingots.steel": "Steel Ingots",
|
||||||
"tag.item.c.ingots.aluminum": "Aluminum Ingots"
|
"tag.item.c.ingots.aluminum": "Aluminum Ingots",
|
||||||
|
|
||||||
|
|
||||||
|
"aphelion.command.station.orbit.set": "Set station (%s, %s)'s orbit to %s",
|
||||||
|
"aphelion.command.station.orbit.get": "Station (%s, %s)'s orbit is assigned to %s",
|
||||||
|
"aphelion.command.station.orbit.get.unassigned": "Station (%s, %s)'s orbit is not assigned",
|
||||||
|
"aphelion.command.station.orbit.cleared": "Cleared station (%s, %s)'s orbit",
|
||||||
|
"aphelion.command.station.orbit.clearall": "Cleared all station orbits",
|
||||||
|
"aphelion.command.station.orbit.overwriteall": "Set all existing station orbits with %s (unassigned stations were not affected)",
|
||||||
|
"aphelion.command.station.orbit.debug.posToKey": "Key of station (%s, %s) is %s",
|
||||||
|
"aphelion.command.station.orbit.debug.keyToPos": "Key %s belongs to station %s",
|
||||||
|
"aphelion.command.station.teleport.success": "Teleported %s to station %s, id: %s",
|
||||||
|
"aphelion.command.station.teleport.failure": "Failed to teleport, entity is null",
|
||||||
|
"aphelion.command.station.orbit.debug.getPartition": "Partition of %s, %s is %s"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user