Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/vanish' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Caedis committed Jan 14, 2025
2 parents b7b6593 + 512dfce commit d34ab17
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 12 deletions.
4 changes: 2 additions & 2 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
dependencies {

api("com.github.GTNewHorizons:GTNHLib:0.6.0:dev")
compileOnly("com.github.GTNewHorizons:NotEnoughItems:2.7.8-GTNH:dev")
compileOnly("com.github.GTNewHorizons:EnderIO:2.9.0:dev")
compileOnly("com.github.GTNewHorizons:NotEnoughItems:2.7.8-GTNH:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:EnderIO:2.9.0:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:Random-Things:2.5.3:dev") {transitive = false}
compileOnly("com.github.GTNewHorizons:Navigator:1.0.15:dev")
compileOnly('org.jetbrains:annotations:25.0.0')
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/serverutils/ServerUtilitiesConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ public static class General {
+ "If set to DEFAULT, it will only merge on singleplayer worlds.")
@Config.DefaultEnum("TRUE")
public EnumTristate merge_offline_mode_players;

@Config.Comment({ "Backports 1.20's 'pause-when-empty-seconds' server property", "Default value: 0 (off)" })
@Config.DefaultBoolean(true)
public boolean enable_pause_when_empty_property;
}

public static class Teams {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/serverutils/command/CmdBackup.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public CmdBackupGetSize(String s) {
public void processCommand(ICommandSender sender, String[] args) {
String sizeW = FileUtils.getSizeString(sender.getEntityWorld().getSaveHandler().getWorldDirectory());
String sizeT = FileUtils.getSizeString(BackupTask.BACKUP_FOLDER);
sender.addChatMessage(ServerUtilities.lang(sender, "cmd.backup_not_running", sizeW, sizeT));
sender.addChatMessage(ServerUtilities.lang(sender, "cmd.backup_size", sizeW, sizeT));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import serverutils.ServerUtilitiesConfig;
import serverutils.command.chunks.CmdChunks;
import serverutils.command.pausewhenempty.CmdPauseWhenEmpty;
import serverutils.command.pregen.CmdPregen;
import serverutils.command.ranks.CmdRanks;
import serverutils.command.team.CmdTeam;
Expand Down Expand Up @@ -38,6 +39,10 @@ public static void registerCommands(FMLServerStartingEvent event) {
if (ServerUtilitiesConfig.auto_shutdown.enabled) {
event.registerServerCommand(new CmdShutdownTime());
}

if (ServerUtilitiesConfig.general.enable_pause_when_empty_property) {
event.registerServerCommand(new CmdPauseWhenEmpty());
}
}

if (commands.inv) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package serverutils.command.pausewhenempty;

import serverutils.lib.command.CmdTreeBase;

public class CmdPauseWhenEmpty extends CmdTreeBase {

public CmdPauseWhenEmpty() {
super("pause_when_empty");
addSubcommand(new CmdPauseWhenEmptySet());
addSubcommand(new CmdPauseWhenEmptyOneshot());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package serverutils.command.pausewhenempty;

import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;

import serverutils.ServerUtilities;
import serverutils.data.IPauseWhenEmpty;
import serverutils.lib.command.CmdBase;

public class CmdPauseWhenEmptyOneshot extends CmdBase {

public CmdPauseWhenEmptyOneshot() {
super("oneshot", Level.OP);
}

@Override
public void processCommand(ICommandSender sender, String[] args) {
checkArgs(sender, args, 1);
int newValue = parseIntWithMin(sender, args[0], -1);

if (MinecraftServer.getServer() instanceof IPauseWhenEmpty pauseWhenEmpty) {
pauseWhenEmpty.serverUtilities$setPauseWhenEmptySeconds(newValue, true);
sender.addChatMessage(ServerUtilities.lang(sender, "cmd.pause_when_empty_oneshot", newValue));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package serverutils.command.pausewhenempty;

import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;

import serverutils.ServerUtilities;
import serverutils.data.IPauseWhenEmpty;
import serverutils.lib.command.CmdBase;

public class CmdPauseWhenEmptySet extends CmdBase {

CmdPauseWhenEmptySet() {
super("set", Level.OP);
}

@Override
public void processCommand(ICommandSender sender, String[] args) {
checkArgs(sender, args, 1);
int newValue = parseIntWithMin(sender, args[0], 0);

if (MinecraftServer.getServer() instanceof IPauseWhenEmpty pauseWhenEmpty) {
pauseWhenEmpty.serverUtilities$setPauseWhenEmptySeconds(newValue, false);
sender.addChatMessage(ServerUtilities.lang(sender, "cmd.pause_when_empty_updated", newValue));
}
}
}
8 changes: 8 additions & 0 deletions src/main/java/serverutils/data/IPauseWhenEmpty.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package serverutils.data;

public interface IPauseWhenEmpty {

int serverUtilities$getPauseWhenEmptySeconds();

void serverUtilities$setPauseWhenEmptySeconds(int value, boolean oneshot);
}
9 changes: 8 additions & 1 deletion src/main/java/serverutils/mixin/Mixins.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package serverutils.mixin;

import static serverutils.ServerUtilitiesConfig.commands;
import static serverutils.ServerUtilitiesConfig.general;
import static serverutils.ServerUtilitiesConfig.ranks;
import static serverutils.mixin.TargetedMod.RANDOMTHINGS;
import static serverutils.mixin.TargetedMod.VANILLA;
Expand Down Expand Up @@ -38,7 +39,13 @@ public enum Mixins {
"minecraft.vanish.MixinItemInWorldManager")),
HIDE_VANISHED_FROM_DETECTOR(new Builder("Hide vanished players from the RandomThings online detector")
.addTargetedMod(RANDOMTHINGS).setSide(Side.SERVER).setPhase(Phase.LATE).setApplyIf(() -> commands.vanish)
.addMixinClasses("randomthings.MixinWorldUtils")),;
.addMixinClasses("randomthings.MixinWorldUtils")),
PAUSE_WHEN_EMPTY(new Builder("Pauses the server when empty after X seconds; Servers Only").setPhase(Phase.EARLY)
.setSide(Side.SERVER).addTargetedMod(TargetedMod.VANILLA)
.addMixinClasses(
"minecraft.MixinMinecraftServer_PauseWhenEmpty",
"minecraft.MixinDedicatedServer_PauseWhenEmpty")
.setApplyIf(() -> general.enable_pause_when_empty_property)),;

private final List<String> mixinClasses;
private final Supplier<Boolean> applyIf;
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/serverutils/task/backup/BackupTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,22 +140,22 @@ public static void clearOldBackups() {
file -> backups.delete_custom_name_backups || BACKUP_NAME_PATTERN.matcher(file.getName()).matches())
.sorted(Comparator.comparingLong(File::lastModified)).collect(Collectors.toList());

int maxGb = backups.max_folder_size;
if (maxGb > 0) {
long currentSize = backupFiles.stream().mapToLong(file -> FileUtils.getSize(file, SizeUnit.GB)).sum();
if (currentSize <= maxGb) return;
deleteOldBackups(backupFiles, currentSize, maxGb);
long maxSize = backups.max_folder_size * SizeUnit.GB.getSize();
if (maxSize > 0) {
long currentSize = backupFiles.stream().mapToLong(FileUtils::getSize).sum();
if (currentSize <= maxSize) return;
deleteOldBackups(backupFiles, currentSize, maxSize);

} else if (backupFiles.size() > backups.backups_to_keep) {
deleteExcessBackups(backupFiles);
}
}

private static void deleteOldBackups(List<File> backupFiles, long currentSize, int maxGb) {
private static void deleteOldBackups(List<File> backupFiles, long currentSize, long maxSize) {
int deleted = 0;
for (File file : backupFiles) {
if (currentSize <= maxGb) break;
currentSize -= FileUtils.getSize(file, SizeUnit.GB);
if (currentSize <= maxSize) break;
currentSize -= FileUtils.getSize(file);
ServerUtilities.LOGGER.info("Deleting old backup: {}", file.getPath());
FileUtils.delete(file);
deleted++;
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/assets/serverutilities/lang/en_US.lang
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,12 @@ serverutilities.gui.backup.error=An error occured while restoring backup!
serverutilities.gui.backup.delete_confirm=Are you sure you want to §c§ldelete§r this backup?
serverutilities.gui.backup.restore_confirm=Are you sure you want to §a§lrestore§r this backup?

# Pause When Empty
cmd.pause_when_empty_updated=Server property 'pause-when-empty-seconds' set to %d
cmd.pause_when_empty_oneshot='pause-when-empty-seconds' temporarily set to %d until next resume. Set to -1 to disable one shot
commands.pause_when_empty.set.usage=/pause_when_empty set <seconds> (0 to disable)
commands.pause_when_empty.oneshot.usage=/pause_when_empty oneshot <seconds> (old value is applied on the next resume; 0 to disable pausing; -1 to disable the oneshot)

# Gui
## Buttons
gui.accept=Accept
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package serverutils.mixins.early.minecraft;

import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.dedicated.PropertyManager;

import org.spongepowered.asm.mixin.Mixin;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import serverutils.data.IPauseWhenEmpty;

@Mixin(DedicatedServer.class)
public class MixinDedicatedServer_PauseWhenEmpty implements IPauseWhenEmpty {

@Shadow
private PropertyManager settings;

@Unique
private int serverUtilities$pauseWhenEmptySeconds = 0;

@Unique
private int serverUtilities$pauseWhenEmptySecondsOneShot = -1;

@Override
public int serverUtilities$getPauseWhenEmptySeconds() {
return serverUtilities$pauseWhenEmptySecondsOneShot > -1 ? serverUtilities$pauseWhenEmptySecondsOneShot
: serverUtilities$pauseWhenEmptySeconds;
}

@Override
public void serverUtilities$setPauseWhenEmptySeconds(int value, boolean oneshot) {
if (oneshot) {
serverUtilities$pauseWhenEmptySecondsOneShot = Math.max(value, -1);
} else {
serverUtilities$pauseWhenEmptySeconds = Math.max(value, 0);
settings.setProperty("pause-when-empty-seconds", serverUtilities$pauseWhenEmptySeconds);
settings.saveProperties();
}
}

@Inject(
method = "startServer",
at = @At(
value = "INVOKE",
target = "Lcpw/mods/fml/common/FMLCommonHandler;onServerStarted()V",
remap = false,
shift = At.Shift.AFTER))
public void su$setupServer(CallbackInfoReturnable<Boolean> cir) {
serverUtilities$pauseWhenEmptySeconds = settings.getIntProperty("pause-when-empty-seconds", 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package serverutils.mixins.early.minecraft;

import net.minecraft.network.NetworkSystem;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.management.ServerConfigurationManager;

import org.spongepowered.asm.mixin.Mixin;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import serverutils.ServerUtilities;
import serverutils.data.IPauseWhenEmpty;

@Mixin(MinecraftServer.class)
public abstract class MixinMinecraftServer_PauseWhenEmpty {

@Shadow
public abstract int getCurrentPlayerCount();

@Shadow
private ServerConfigurationManager serverConfigManager;

@Shadow
protected abstract void saveAllWorlds(boolean dontLog);

@Shadow
public abstract NetworkSystem func_147137_ag();

@Shadow
public abstract int getTickCounter();

@Unique
private int serverUtilities$emptyTicks = 0;
@Unique
private boolean serverUtilities$wasPaused = false;

@Inject(method = "tick", at = @At("HEAD"), cancellable = true, order = 9000)
public void serverUtilities$tick(CallbackInfo ci) {
if ((Object) this instanceof DedicatedServer ds && ds instanceof IPauseWhenEmpty p) {
int pauseTicks = p.serverUtilities$getPauseWhenEmptySeconds() * 20;
if (pauseTicks > 0) {
if (this.getCurrentPlayerCount() == 0) {
this.serverUtilities$emptyTicks++;
} else {
this.serverUtilities$emptyTicks = 0;
}

if (serverUtilities$emptyTicks >= pauseTicks) {
if (!serverUtilities$wasPaused) {
ServerUtilities.LOGGER.info(
"Server empty for {} seconds, saving and pausing",
p.serverUtilities$getPauseWhenEmptySeconds());
this.serverConfigManager.saveAllPlayerData();
this.saveAllWorlds(true);
serverUtilities$wasPaused = true;
}
// to finish saving chunks
net.minecraftforge.common.chunkio.ChunkIOExecutor.tick();
// to process new connections
this.func_147137_ag().networkTick();
// to process console commands
ds.executePendingCommands();
ci.cancel();
return;
}
}

if (serverUtilities$wasPaused) {
ServerUtilities.LOGGER.info("Resuming server");
serverUtilities$wasPaused = false;
// reset the oneshot value to -1
p.serverUtilities$setPauseWhenEmptySeconds(-1, true);
}
}
}
}

0 comments on commit d34ab17

Please sign in to comment.