Skip to content
Draft
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cef942b
feat: bump project to minecraft 26.1.2
jimchen5209 Apr 18, 2026
60dd28b
ci: Java 25
jimchen5209 Apr 18, 2026
081600a
build(docker): bump Minecraft version to 26.1.2
jimchen5209 Apr 19, 2026
b5eddbb
build(docker): bump Easy Recipe to 1.4.7
jimchen5209 Apr 19, 2026
a67bda2
build: update fabric
jimchen5209 Apr 19, 2026
6891428
build: updater gradle wrapper to 9.4.1
jimchen5209 Apr 19, 2026
22914c7
build: bump galaxy lib to 9546e40
jimchen5209 Apr 19, 2026
708259c
build: update action versions in workflow
jimchen5209 Apr 19, 2026
ea42132
ci: fix submodule
jimchen5209 Apr 19, 2026
a1c9361
build: add sha512 checksums to mods
jimchen5209 Apr 19, 2026
1588b3a
build(docker): update krypton
jimchen5209 Apr 26, 2026
1d0cc74
build(docker): add checksum verification for fabric-server-launch.jar
jimchen5209 Apr 26, 2026
45f9922
fix: restore entity tag check to ensure only specific leaked entities…
jimchen5209 Apr 26, 2026
a67c6f3
refactor: remove redundant safe calls and deprecate removeComponentsF…
jimchen5209 Apr 26, 2026
21ce790
refactor: restore changes of CustomItem.kt
jimchen5209 Apr 26, 2026
7da8856
refactor: migrate real-time tracking to ServerClockManager
jimchen5209 Apr 26, 2026
dce3bdc
refactor: clean up
jimchen5209 Apr 26, 2026
c58b9e2
refactor: restore changes from ModelCustomBlock
jimchen5209 Apr 26, 2026
cbf5800
refactor: restore changes in Creative.kt
jimchen5209 Apr 26, 2026
01595b1
refactor: restore Exchange and clean up
jimchen5209 Apr 27, 2026
140f509
fix: ItemStack init too early
jimchen5209 Apr 27, 2026
5ecabdd
refactor: migrate delay calls to Kotlin Duration API
jimchen5209 Apr 27, 2026
82fe804
docs: update copyright
jimchen5209 Apr 27, 2026
bd637f3
fix: try force disable atomic move and hardlink
jimchen5209 Apr 27, 2026
d94841c
fix: drop the unused serverWorld lambda parameter in Harvest.kt
jimchen5209 Apr 27, 2026
0170867
fix: try disable hardlink only
jimchen5209 Apr 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
docker:
# specify the version you desire here
- image: eclipse-temurin:21-jdk-noble
- image: eclipse-temurin:25-jdk-noble
resource_class: large

working_directory: ~/repo
Expand Down
26 changes: 11 additions & 15 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
- name: cache
uses: actions/cache@v4
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # 5.0.5
with:
path: |
~/.gradle/caches
Expand All @@ -18,16 +18,16 @@ jobs:
restore-keys: |
caches-
- name: JDK
uses: actions/setup-java@v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
with:
distribution: "temurin"
java-version: "21"
java-version: "25"
- name: Gradle
uses: gradle/actions/wrapper-validation@v4
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Build
run: ./gradlew --no-daemon build
- name: Upload-Artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: jar
path: build/libs/Galaxy.jar
Expand All @@ -45,20 +45,16 @@ jobs:
shell: bash
run: echo IMAGE_TAG=$([ "$GITHUB_REF" = "refs/heads/master" ] && echo "latest" || ([ "$GITHUB_EVENT_NAME" = 'pull_request' ] && echo pr-${{github.event.pull_request.number}} || echo ${GITHUB_REF##*/})) >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
- name: Checkout submodules
shell: bash
run: |
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
git submodule sync --recursive
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
- uses: actions/download-artifact@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
with:
submodules: recursive
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # 8.0.1
with:
name: jar
path: docker/mods/Galaxy.jar
- name: login
if: env.USERNAME != '' && env.PASSWORD != ''
uses: docker/login-action@v3
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # 4.1.0
with:
registry: harbor.k8s.oktw.one
username: ${{ secrets.OKTW_HARBOR_USERNAME }}
Expand Down
23 changes: 11 additions & 12 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,38 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
// "maven-publish"
kotlin("jvm") version "2.3.0"
id("net.fabricmc.fabric-loom-remap") version "1.14-SNAPSHOT"
id("net.fabricmc.fabric-loom") version "1.16.1"
}

val version = "0.0.1"
val group = "one.oktw"

val minecraftVersion = "1.21.11"
val fabricLoaderVersion = "0.18.3"
val fabricAPIVersion = "0.140.0+1.21.11"
val galaxyLibVersion = "2235da5"
val minecraftVersion = "26.1.2"
val fabricLoaderVersion = "0.19.2"
val fabricAPIVersion = "0.146.1+26.1.2"
val galaxyLibVersion = "9546e40"

repositories {
mavenCentral()
maven(url = "https://jitpack.io")
maven(url = "https://maven.fabricmc.net/")
}

base {
archivesName.set("Galaxy")
}

java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_25
targetCompatibility = JavaVersion.VERSION_25
}

tasks.withType<KotlinCompile>().configureEach {
compilerOptions {
apiVersion = KotlinVersion.KOTLIN_2_0
languageVersion = KotlinVersion.KOTLIN_2_0
jvmTarget = JvmTarget.JVM_21
jvmTarget = JvmTarget.JVM_25
}
}

Expand All @@ -52,11 +52,10 @@ fabricApi {
dependencies {
// Core
minecraft("com.mojang:minecraft:${minecraftVersion}")
mappings(loom.officialMojangMappings())
modImplementation("net.fabricmc:fabric-loader:${fabricLoaderVersion}")
implementation("net.fabricmc:fabric-loader:${fabricLoaderVersion}")

// fabric api
modImplementation("net.fabricmc.fabric-api:fabric-api:${fabricAPIVersion}") {
implementation("net.fabricmc.fabric-api:fabric-api:${fabricAPIVersion}") {
val gametest = fabricApi.module("fabric-gametest-api-v1", fabricAPIVersion) // Unused and cause client Registry remapping failed.
exclude(gametest.group, gametest.name)
}
Expand Down
2 changes: 1 addition & 1 deletion docker
Submodule docker updated 1 files
+39 −12 Dockerfile
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 1 addition & 1 deletion gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2025
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
Expand Down Expand Up @@ -33,7 +33,7 @@

@Mixin(EmoteCommands.class)
public class MixinPlayerChat_EmoteCommands {
@Redirect(method = "method_43645", at = @At(
@Redirect(method = "lambda$register$1", at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/players/PlayerList;broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Lnet/minecraft/commands/CommandSourceStack;Lnet/minecraft/network/chat/ChatType$Bound;)V",
ordinal = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2025
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
Expand Down Expand Up @@ -35,7 +35,7 @@
@Mixin(SayCommand.class)
public class MixinPlayerChat_SayCommand {
@Inject(
method = "method_43657",
method = "lambda$register$1",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/players/PlayerList;broadcastChatMessage(Lnet/minecraft/network/chat/PlayerChatMessage;Lnet/minecraft/commands/CommandSourceStack;Lnet/minecraft/network/chat/ChatType$Bound;)V",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2025
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
Expand Down Expand Up @@ -75,7 +75,7 @@ public abstract class MixinAsyncChunk_IOWorker {

@Inject(method = "<init>", at = @At("RETURN"))
private void parallelExecutor(RegionStorageInfo storageKey, Path directory, boolean dsync, CallbackInfo ci) {
pendingWrites = new ConcurrentSkipListMap<>(Comparator.comparingLong(ChunkPos::toLong));
pendingWrites = new ConcurrentSkipListMap<>(Comparator.comparingLong(ChunkPos::pack));
consecutiveExecutor = new KotlinCoroutineTaskExecutor(3 /* FOREGROUND,BACKGROUND,SHUTDOWN */, "IOWorker-" + storageKey.type());
}

Expand All @@ -87,7 +87,7 @@ private void parallelExecutor(RegionStorageInfo storageKey, Path directory, bool
private void storePendingChunk() {
if (!this.pendingWrites.isEmpty() && !writeLock.getAndSet(true)) {
HashMap<Long, ArrayList<Tuple<ChunkPos, IOWorker.PendingStore>>> map = new HashMap<>();
pendingWrites.forEach((pos, result) -> map.computeIfAbsent(ChunkPos.asLong(pos.getRegionX(), pos.getRegionZ()), k -> new ArrayList<>()).add(new Tuple<>(pos, result)));
pendingWrites.forEach((pos, result) -> map.computeIfAbsent(ChunkPos.pack(pos.getRegionX(), pos.getRegionZ()), k -> new ArrayList<>()).add(new Tuple<>(pos, result)));
map.values().forEach(list ->
consecutiveExecutor.schedule(new StrictQueue.RunnableWithPriority(Priority.FOREGROUND.ordinal(), () -> list.forEach(pair -> runStore(pair.getA(), pair.getB()))))
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2025
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
Expand Down Expand Up @@ -54,7 +54,7 @@ private void noBlockingMove(ServerboundMovePlayerPacket packet, CallbackInfo ci)

int x = SectionPos.posToSectionCoord(clampHorizontal(packet.getX(this.player.getX())));
int z = SectionPos.posToSectionCoord(clampHorizontal(packet.getZ(this.player.getZ())));
if (!player.level().getChunkSource().isPositionTicking(ChunkPos.asLong(x, z))) {
if (!player.level().getChunkSource().isPositionTicking(ChunkPos.pack(x, z))) {
player.setDeltaMovement(Vec3.ZERO);
teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
ci.cancel();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2025
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
Expand Down Expand Up @@ -36,8 +36,8 @@ public abstract class MixinMapExistingChunk_MapItem {
private LevelChunk getExistingChunk(Level world, int x, int z) {
ServerLevel serverWorld = (ServerLevel) world;
ChunkPos chunkPos = new ChunkPos(x, z);
if (serverWorld.getChunkSource().isPositionTicking(chunkPos.toLong())) { // TODO check this
LevelChunk chunk = world.getChunkSource().getChunkNow(chunkPos.x, chunkPos.z);
if (serverWorld.getChunkSource().isPositionTicking(chunkPos.pack())) { // TODO check this
LevelChunk chunk = world.getChunkSource().getChunkNow(x, z);
if (chunk != null) return chunk;
}
return new EmptyLevelChunk(world, new ChunkPos(x, z), world.registryAccess().lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.PLAINS));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2025
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
Expand All @@ -27,7 +27,7 @@
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(Entity.class)
public abstract class MixinThrownCountdown_Entity implements IThrownCountdown_Entity {
Expand All @@ -37,9 +37,9 @@ public abstract class MixinThrownCountdown_Entity implements IThrownCountdown_En
@Shadow
public abstract void discard();

@Inject(method = "updateInWaterStateAndDoWaterCurrentPushing",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;doWaterSplashEffect()V"))
private void countIntoWater(CallbackInfo ci) {
@Inject(method = "updateFluidInteraction",
at = @At(value = "RETURN"))
private void countIntoWater(CallbackInfoReturnable<Boolean> ci) {
//noinspection ConstantConditions
if (((Object) this) instanceof Arrow || ((Object) this) instanceof SpectralArrow) {
if (intoWater > 10) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.spongepowered.common.mixin.realtime.world;

import net.minecraft.core.Holder;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.clock.ServerClockManager;
import net.minecraft.world.clock.WorldClock;
import net.minecraft.world.level.gamerules.GameRules;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.common.bridge.RealTimeTrackingBridge;

import java.util.Map;

@Mixin(ServerClockManager.class)
public abstract class ServerClockManagerMixin_RealTime implements RealTimeTrackingBridge {
@Shadow
private MinecraftServer server;

@Final
@Shadow
private Map<Holder<WorldClock>, ServerClockManager.ClockInstance> clocks;

@Inject(method = "tick", at=@At("HEAD"))
private void realTimeImpl$fixTimeOfDayForRealTime(CallbackInfo ci){
//noinspection deprecation
if (this.server.getGlobalGameRules().get(GameRules.ADVANCE_TIME)) {
// Subtract the one the original tick method is going to add
long diff = this.realTimeBridge$getRealTimeTicks() - 1;
// Don't set if we're not changing it as other mods might be listening for changes
if (diff > 0) {
for (int i = 0; i < diff; i++) {
this.clocks.values().forEach(ServerClockManager.ClockInstance::tick);
}
}
}
}

@Override
public long realTimeBridge$getRealTimeTicks() {
if (this.server != null) {
return ((RealTimeTrackingBridge) this.server).realTimeBridge$getRealTimeTicks();
}
return 1;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* OKTW Galaxy Project
* Copyright (C) 2018-2025
* Copyright (C) 2018-2026
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
Expand Down Expand Up @@ -49,24 +49,14 @@
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.gamerules.GameRules;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.common.bridge.RealTimeTrackingBridge;

@Mixin(ServerLevel.class)
public abstract class ServerLevelMixin_RealTime extends Level implements RealTimeTrackingBridge {
@Shadow
@Final
private ServerLevelData serverLevelData;

protected ServerLevelMixin_RealTime(WritableLevelData properties, ResourceKey<Level> registryRef, RegistryAccess registryManager, Holder<DimensionType> dimensionEntry, boolean isClient, boolean debugWorld, long seed, int maxChainedNeighborUpdates) {
super(properties, registryRef, registryManager, dimensionEntry, isClient, debugWorld, seed, maxChainedNeighborUpdates);
}
Expand All @@ -75,21 +65,6 @@ protected ServerLevelMixin_RealTime(WritableLevelData properties, ResourceKey<Le
@Nullable
public abstract MinecraftServer getServer();

@Shadow
public abstract void setDayTime(long timeOfDay);

@Inject(method = "tickTime", at = @At("HEAD"))
private void realTimeImpl$fixTimeOfDayForRealTime(CallbackInfo ci) {
if (this.serverLevelData.getGameRules().get(GameRules.ADVANCE_TIME)) {
// Subtract the one the original tick method is going to add
long diff = this.realTimeBridge$getRealTimeTicks() - 1;
// Don't set if we're not changing it as other mods might be listening for changes
if (diff > 0) {
this.setDayTime(this.levelData.getDayTime() + diff);
}
}
}

@Override
public long realTimeBridge$getRealTimeTicks() {
if (this.getServer() != null) {
Expand Down
Loading