From a0794eaab90efbc2199e86c59851b99e46ea859e Mon Sep 17 00:00:00 2001 From: DoggySazHi Date: Mon, 24 Jun 2024 21:47:56 -0700 Subject: [PATCH 1/2] Implement asynchronous NBT saving --- .../nitori/core/MixinCraftPlayer.java | 32 +++++++++++++++++++ .../nitori/core/MixinLevelStorageAccess.java | 32 +++++++++++++++++++ .../nitori/core/MixinPlayerList.java | 28 ++++++++++++++++ src/main/resources/mixins.core.json | 5 ++- 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java create mode 100644 src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java create mode 100644 src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java diff --git a/src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java b/src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java new file mode 100644 index 0000000..4a4f8b1 --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java @@ -0,0 +1,32 @@ +package net.gensokyoreimagined.nitori.core; + +import net.minecraft.Util; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.storage.PlayerDataStorage; +import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.concurrent.CompletableFuture; + +@Mixin(CraftPlayer.class) +public class MixinCraftPlayer { + @Redirect(method = "saveData", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;save(Lnet/minecraft/world/entity/player/Player;)V")) + private void gensouHacks$savePlayerData(PlayerDataStorage instance, Player path) { + Runnable writeRunnable = () -> { + var craftPlayer = (CraftPlayer) (Object) this; + var server = craftPlayer.getServer(); + + if (server instanceof CraftServer craftServer) { + var handle = craftPlayer.getHandle(); + var playerIo = craftServer.getHandle().playerIo; + playerIo.save(handle); + } + }; + + var ioExecutor = Util.backgroundExecutor(); + CompletableFuture.runAsync(writeRunnable, ioExecutor); + } +} diff --git a/src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java b/src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java new file mode 100644 index 0000000..3ec8dae --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java @@ -0,0 +1,32 @@ +package net.gensokyoreimagined.nitori.core; + +import net.minecraft.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.storage.LevelStorageSource; +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.Redirect; + +import java.util.concurrent.CompletableFuture; + +@Mixin(LevelStorageSource.LevelStorageAccess.class) +public abstract class MixinLevelStorageAccess { + @Shadow protected abstract void saveLevelData(CompoundTag nbt); + + @Redirect(method = "modifyLevelDataWithoutDatafix", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V")) + private void gensouHacks$saveLevelData(LevelStorageSource.LevelStorageAccess levelStorageAccess, CompoundTag compoundTag) { + Runnable writeRunnable = () -> saveLevelData(compoundTag); + + var ioExecutor = Util.backgroundExecutor(); + CompletableFuture.runAsync(writeRunnable, ioExecutor); + } + + @Redirect(method = "saveDataTag(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/level/storage/WorldData;Lnet/minecraft/nbt/CompoundTag;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveLevelData(Lnet/minecraft/nbt/CompoundTag;)V")) + private void gensouHacks$saveLevelData2(LevelStorageSource.LevelStorageAccess levelStorageAccess, CompoundTag compoundTag) { + Runnable writeRunnable = () -> saveLevelData(compoundTag); + + var ioExecutor = Util.backgroundExecutor(); + CompletableFuture.runAsync(writeRunnable, ioExecutor); + } +} diff --git a/src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java b/src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java new file mode 100644 index 0000000..3e7758c --- /dev/null +++ b/src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java @@ -0,0 +1,28 @@ +package net.gensokyoreimagined.nitori.core; + +import net.minecraft.Util; +import net.minecraft.server.players.PlayerList; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.storage.PlayerDataStorage; +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.Redirect; + +import java.util.concurrent.CompletableFuture; + +@Mixin(PlayerList.class) +public class MixinPlayerList { + @Final + @Shadow + public PlayerDataStorage playerIo; + + @Redirect(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/PlayerDataStorage;save(Lnet/minecraft/world/entity/player/Player;)V")) + private void gensouHacks$savePlayerData(PlayerDataStorage instance, Player player) { + Runnable writeRunnable = () -> playerIo.save(player); + + var ioExecutor = Util.backgroundExecutor(); + CompletableFuture.runAsync(writeRunnable, ioExecutor); + } +} diff --git a/src/main/resources/mixins.core.json b/src/main/resources/mixins.core.json index 0e7ef4a..df12eec 100755 --- a/src/main/resources/mixins.core.json +++ b/src/main/resources/mixins.core.json @@ -26,6 +26,9 @@ "MixinWorldGenRegion", "ChunkMapMixin", "ChunkMapMixin$TrackedEntity", - "MixinReobfServer" + "MixinReobfServer", + "MixinLevelStorageAccess", + "MixinPlayerList", + "MixinCraftPlayer" ] } From 71fc6f332ba18c467b45718adc6e9e40e7e6fe91 Mon Sep 17 00:00:00 2001 From: DoggySazHi Date: Mon, 24 Jun 2024 21:49:59 -0700 Subject: [PATCH 2/2] spotless applied --- .../nitori/core/MixinCraftPlayer.java | 14 ++++++++++++++ .../nitori/core/MixinLevelStorageAccess.java | 14 ++++++++++++++ .../nitori/core/MixinPlayerList.java | 14 ++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java b/src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java index 4a4f8b1..78dd35f 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java +++ b/src/main/java/net/gensokyoreimagined/nitori/core/MixinCraftPlayer.java @@ -1,3 +1,17 @@ +// Nitori Copyright (C) 2024 Gensokyo Reimagined +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . package net.gensokyoreimagined.nitori.core; import net.minecraft.Util; diff --git a/src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java b/src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java index 3ec8dae..c8b75c4 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java +++ b/src/main/java/net/gensokyoreimagined/nitori/core/MixinLevelStorageAccess.java @@ -1,3 +1,17 @@ +// Nitori Copyright (C) 2024 Gensokyo Reimagined +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . package net.gensokyoreimagined.nitori.core; import net.minecraft.Util; diff --git a/src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java b/src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java index 3e7758c..6f02988 100644 --- a/src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java +++ b/src/main/java/net/gensokyoreimagined/nitori/core/MixinPlayerList.java @@ -1,3 +1,17 @@ +// Nitori Copyright (C) 2024 Gensokyo Reimagined +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . package net.gensokyoreimagined.nitori.core; import net.minecraft.Util;