diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSky.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSky.java
index 0d63975..41e326c 100644
--- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSky.java
+++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSky.java
@@ -1,18 +1,16 @@
package io.github.slimeistdev.crystalline_sky;
-import net.fabricmc.api.ModInitializer;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class CrystallineSky implements ModInitializer {
+public class CrystallineSky {
public static final String ID = "crystalline_sky";
public static final Logger LOG = LoggerFactory.getLogger(ID);
- @Override
- public void onInitialize() {
+ public static void init() {
ModSetup.init();
}
diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java
index c69f6ea..2507f50 100644
--- a/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java
+++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/CrystallineSkyClient.java
@@ -1,28 +1,29 @@
package io.github.slimeistdev.crystalline_sky;
+import com.mojang.blaze3d.platform.InputConstants;
import io.github.slimeistdev.crystalline_sky.mixin_ducks.client.DebugRenderer_Duck;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineBlocks;
import io.github.slimeistdev.crystalline_sky.registry.CrystallineItems;
import io.github.slimeistdev.crystalline_sky.registry.client.CrystallineRenderTypes;
-import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
-import net.minecraft.world.level.block.LightBlock;
-import net.minecraft.client.renderer.item.ItemProperties;
+import net.minecraft.ChatFormatting;
import net.minecraft.client.KeyMapping;
-import com.mojang.blaze3d.platform.InputConstants;
+import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.core.component.DataComponents;
-import net.minecraft.world.item.component.BlockItemStateProperties;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
-import net.minecraft.ChatFormatting;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.item.component.BlockItemStateProperties;
+import net.minecraft.world.level.block.LightBlock;
import org.lwjgl.glfw.GLFW;
-public class CrystallineSkyClient implements ClientModInitializer {
- @Override
- public void onInitializeClient() {
+@Environment(EnvType.CLIENT)
+public class CrystallineSkyClient {
+ public static void init() {
BlockRenderLayerMap.INSTANCE.putBlock(CrystallineBlocks.SKY, CrystallineRenderTypes.SKY);
BlockRenderLayerMap.INSTANCE.putBlock(CrystallineBlocks.WEEPING_SKY, CrystallineRenderTypes.SKY);
diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/annotation/multiloader/ImplClass.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/annotation/multiloader/ImplClass.java
new file mode 100644
index 0000000..6f14ff8
--- /dev/null
+++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/annotation/multiloader/ImplClass.java
@@ -0,0 +1,33 @@
+/*
+ * Steam 'n' Rails
+ * Copyright (c) 2025 The Railways Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package io.github.slimeistdev.crystalline_sky.annotation.multiloader;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Used to mark classes that are used via abstracted loader-specific methods.
+ *
+ * Meant purely for documentation and does not exist at compile-time or runtime.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+public @interface ImplClass { }
diff --git a/common/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/Env.java b/common/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/Env.java
new file mode 100644
index 0000000..1ea71ac
--- /dev/null
+++ b/common/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/Env.java
@@ -0,0 +1,52 @@
+/*
+ * Steam 'n' Rails
+ * Copyright (c) 2022-2024 The Railways Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package io.github.slimeistdev.crystalline_sky.multiloader;
+
+import dev.architectury.injectables.annotations.ExpectPlatform;
+import org.jetbrains.annotations.ApiStatus.Internal;
+
+import java.util.function.Supplier;
+
+public enum Env {
+ CLIENT, SERVER;
+
+ public static final Env CURRENT = getCurrent();
+
+ public boolean isCurrent() {
+ return this == CURRENT;
+ }
+
+ public void runIfCurrent(Supplier run) {
+ if (isCurrent())
+ run.get().run();
+ }
+
+ public static T unsafeRunForDist(Supplier> clientTarget, Supplier> serverTarget) {
+ return switch (Env.CURRENT) {
+ case CLIENT -> clientTarget.get().get();
+ case SERVER -> serverTarget.get().get();
+ };
+ }
+
+ @Internal
+ @ExpectPlatform
+ private static Env getCurrent() {
+ throw new AssertionError();
+ }
+}
diff --git a/common/src/main/resources/crystalline_sky.mixins.json b/common/src/main/resources/crystalline_sky-common.mixins.json
similarity index 100%
rename from common/src/main/resources/crystalline_sky.mixins.json
rename to common/src/main/resources/crystalline_sky-common.mixins.json
diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyClientImpl.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyClientImpl.java
new file mode 100644
index 0000000..c6edca8
--- /dev/null
+++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyClientImpl.java
@@ -0,0 +1,14 @@
+package io.github.slimeistdev.crystalline_sky.fabric;
+
+import io.github.slimeistdev.crystalline_sky.CrystallineSkyClient;
+import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+
+@Environment(EnvType.CLIENT)
+public class CrystallineSkyClientImpl implements ClientModInitializer {
+ @Override
+ public void onInitializeClient() {
+ CrystallineSkyClient.init();
+ }
+}
diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyImpl.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyImpl.java
new file mode 100644
index 0000000..db147ba
--- /dev/null
+++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/fabric/CrystallineSkyImpl.java
@@ -0,0 +1,12 @@
+package io.github.slimeistdev.crystalline_sky.fabric;
+
+import io.github.slimeistdev.crystalline_sky.CrystallineSky;
+import net.fabricmc.api.ModInitializer;
+
+public class CrystallineSkyImpl implements ModInitializer {
+
+ @Override
+ public void onInitialize() {
+ CrystallineSky.init();
+ }
+}
diff --git a/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/fabric/EnvImpl.java b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/fabric/EnvImpl.java
new file mode 100644
index 0000000..467b8dc
--- /dev/null
+++ b/fabric/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/fabric/EnvImpl.java
@@ -0,0 +1,15 @@
+package io.github.slimeistdev.crystalline_sky.multiloader.fabric;
+
+import io.github.slimeistdev.crystalline_sky.annotation.multiloader.ImplClass;
+import io.github.slimeistdev.crystalline_sky.multiloader.Env;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.loader.api.FabricLoader;
+import org.jetbrains.annotations.ApiStatus.Internal;
+
+@ImplClass
+public class EnvImpl {
+ @Internal
+ public static Env getCurrent() {
+ return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT ? Env.CLIENT : Env.SERVER;
+ }
+}
diff --git a/fabric/src/main/resources/crystalline_sky.mixins.json b/fabric/src/main/resources/crystalline_sky.mixins.json
new file mode 100644
index 0000000..7216cec
--- /dev/null
+++ b/fabric/src/main/resources/crystalline_sky.mixins.json
@@ -0,0 +1,19 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "mixinextras": {
+ "minVersion": "0.5.0"
+ },
+ "package": "io.github.slimeistdev.crystalline_sky.fabric.mixin",
+ "plugin": "io.github.slimeistdev.crystalline_sky.mixin.CrystallineSkyMixinPlugin",
+ "compatibilityLevel": "JAVA_21",
+ "mixins": [
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}
diff --git a/common/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json
similarity index 77%
rename from common/src/main/resources/fabric.mod.json
rename to fabric/src/main/resources/fabric.mod.json
index e4da7c8..b325cc6 100644
--- a/common/src/main/resources/fabric.mod.json
+++ b/fabric/src/main/resources/fabric.mod.json
@@ -18,7 +18,8 @@
"license": "${license}",
"icon": "assets/${modId}/icon.png",
"mixins": [
- "${modId}.mixins.json"
+ "${modId}.mixins.json",
+ "${modId}-common.mixins.json"
],
"depends": {
"minecraft": ">=${mc}",
@@ -29,10 +30,10 @@
},
"entrypoints": {
"main": [
- "io.github.slimeistdev.crystalline_sky.CrystallineSky"
+ "io.github.slimeistdev.crystalline_sky.fabric.CrystallineSkyImpl"
],
"client": [
- "io.github.slimeistdev.crystalline_sky.CrystallineSkyClient"
+ "io.github.slimeistdev.crystalline_sky.fabric.CrystallineSkyClientImpl"
],
"fabric-datagen": [
"io.github.slimeistdev.crystalline_sky.datagen.CrystallineSkyDataGenerator"
diff --git a/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/neoforge/EnvImpl.java b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/neoforge/EnvImpl.java
new file mode 100644
index 0000000..98825bb
--- /dev/null
+++ b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/multiloader/neoforge/EnvImpl.java
@@ -0,0 +1,15 @@
+package io.github.slimeistdev.crystalline_sky.multiloader.neoforge;
+
+import io.github.slimeistdev.crystalline_sky.annotation.multiloader.ImplClass;
+import io.github.slimeistdev.crystalline_sky.multiloader.Env;
+import net.neoforged.api.distmarker.Dist;
+import net.neoforged.fml.loading.FMLEnvironment;
+import org.jetbrains.annotations.ApiStatus.Internal;
+
+@ImplClass
+public class EnvImpl {
+ @Internal
+ public static Env getCurrent() {
+ return FMLEnvironment.dist == Dist.CLIENT ? Env.CLIENT : Env.SERVER;
+ }
+}
diff --git a/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyClientImpl.java b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyClientImpl.java
new file mode 100644
index 0000000..64b7ed5
--- /dev/null
+++ b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyClientImpl.java
@@ -0,0 +1,9 @@
+package io.github.slimeistdev.crystalline_sky.neoforge;
+
+import io.github.slimeistdev.crystalline_sky.CrystallineSkyClient;
+
+public class CrystallineSkyClientImpl {
+ public static void init() {
+ CrystallineSkyClient.init();
+ }
+}
diff --git a/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyImpl.java b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyImpl.java
new file mode 100644
index 0000000..41c68fb
--- /dev/null
+++ b/neoforge/src/main/java/io/github/slimeistdev/crystalline_sky/neoforge/CrystallineSkyImpl.java
@@ -0,0 +1,14 @@
+package io.github.slimeistdev.crystalline_sky.neoforge;
+
+import io.github.slimeistdev.crystalline_sky.CrystallineSky;
+import io.github.slimeistdev.crystalline_sky.multiloader.Env;
+import net.neoforged.fml.common.Mod;
+
+@Mod(CrystallineSky.ID)
+public class CrystallineSkyImpl {
+ public CrystallineSkyImpl() {
+ CrystallineSky.init();
+ //noinspection Convert2MethodRef
+ Env.CLIENT.runIfCurrent(() -> () -> CrystallineSkyClientImpl.init());
+ }
+}
diff --git a/common/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml
similarity index 71%
rename from common/src/main/resources/META-INF/neoforge.mods.toml
rename to neoforge/src/main/resources/META-INF/neoforge.mods.toml
index 6bede7d..7df9f9a 100644
--- a/common/src/main/resources/META-INF/neoforge.mods.toml
+++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml
@@ -12,18 +12,11 @@ authors = "${members}"
displayURL = "${homepage}"
logoFile = "assets/${modId}/icon.png"
-[[mixins]]
-config="${modId}-common.mixins.json"
-
[[mixins]]
config="${modId}.mixins.json"
-[[dependencies."${ modId }"]]
-modId = "connector"
-type = "required"
-versionRange = "*"
-ordering = "NONE"
-side = "BOTH"
+[[mixins]]
+config="${modId}-common.mixins.json"
[[dependencies."${ modId }"]]
modId = "neoforge"
@@ -38,10 +31,3 @@ type = "required"
versionRange = "[${mc},)"
ordering = "NONE"
side = "BOTH"
-
-[[dependencies."${ modId }"]]
-modId = "fabric_api"
-type = "required"
-versionRange = "[${fapi},)"
-ordering = "NONE"
-side = "BOTH"
diff --git a/neoforge/src/main/resources/crystalline_sky.mixins.json b/neoforge/src/main/resources/crystalline_sky.mixins.json
new file mode 100644
index 0000000..af85bfb
--- /dev/null
+++ b/neoforge/src/main/resources/crystalline_sky.mixins.json
@@ -0,0 +1,19 @@
+{
+ "required": true,
+ "minVersion": "0.8",
+ "mixinextras": {
+ "minVersion": "0.5.0"
+ },
+ "package": "io.github.slimeistdev.crystalline_sky.neoforge.mixin",
+ "plugin": "io.github.slimeistdev.crystalline_sky.mixin.CrystallineSkyMixinPlugin",
+ "compatibilityLevel": "JAVA_21",
+ "mixins": [
+ ],
+ "client": [
+ ],
+ "server": [
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
+}