Skip to content

Commit

Permalink
Backport 1.20's 'pause-when-empty-seconds' server property (#470)
Browse files Browse the repository at this point in the history
  • Loading branch information
Caedis authored Jan 13, 2025
1 parent 3601891 commit 6aaff70
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 16 deletions.
18 changes: 9 additions & 9 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ configurations {
}

dependencies {
api("com.github.GTNewHorizons:GTNHLib:0.6.0:dev")
api("com.github.GTNewHorizons:GTNHLib:0.6.1:dev")

compileOnly("com.gtnewhorizons.retrofuturabootstrap:RetroFuturaBootstrap:1.0.2") { transitive = false }

transformedMod("com.github.GTNewHorizons:NotEnoughItems:2.7.11-GTNH:dev") // force a more up-to-date NEI version
transformedModCompileOnly("com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-516-GTNH")
transformedMod("com.github.GTNewHorizons:NotEnoughItems:2.7.15-GTNH:dev") // force a more up-to-date NEI version
transformedModCompileOnly("com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-518-GTNH")
transformedModCompileOnly("com.github.GTNewHorizons:Baubles:1.0.4:dev")
// Transitive updates to make runClient17 work
transformedModCompileOnly("com.github.GTNewHorizons:ForgeMultipart:1.6.0:dev")
transformedModCompileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.51.48:dev")
transformedModCompileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.51.61:dev")
transformedModCompileOnly("com.github.GTNewHorizons:harvestcraft:1.2.3-GTNH:dev")
transformedModCompileOnly("com.github.GTNewHorizons:HungerOverhaul:1.1.0-GTNH:dev")
transformedModCompileOnly("com.github.GTNewHorizons:MrTJPCore:1.2.1:dev") // Do not update, fixed afterwards
transformedModCompileOnly("com.github.GTNewHorizons:Railcraft:9.16.1:dev") { exclude group: "thaumcraft", module: "Thaumcraft" }
transformedModCompileOnly("com.github.GTNewHorizons:TinkersConstruct:1.13.2-GTNH:dev")
transformedModCompileOnly("com.github.GTNewHorizons:MrTJPCore:1.3.0:dev") // Do not update, fixed afterwards
transformedModCompileOnly("com.github.GTNewHorizons:Railcraft:9.16.2:dev") { exclude group: "thaumcraft", module: "Thaumcraft" }
transformedModCompileOnly("com.github.GTNewHorizons:TinkersConstruct:1.13.3-GTNH:dev")
transformedModCompileOnly(rfg.deobf("curse.maven:bibliocraft-228027:2423369"))
transformedModCompileOnly(rfg.deobf("curse.maven:biomes-o-plenty-220318:2499612"))
transformedModCompileOnly("curse.maven:cofh-core-69162:2388751")
Expand All @@ -45,7 +45,7 @@ dependencies {
transformedModCompileOnly(rfg.deobf("curse.maven:glibys-voice-chat-225110:2301492"))

transformedModCompileOnly(rfg.deobf("curse.maven:automagy-222153:2285272"))
transformedModCompileOnly("com.github.GTNewHorizons:Galacticraft:3.3.0-GTNH:dev")
transformedModCompileOnly("com.github.GTNewHorizons:Galacticraft:3.3.1-GTNH:dev")
transformedModCompileOnly("curse.maven:minechem-368422:2905830")
transformedModCompileOnly("curse.maven:thermal-dynamics-227443:2388756")
transformedModCompileOnly("curse.maven:thermal-expansion-69163:2388759")
Expand All @@ -61,7 +61,7 @@ dependencies {
transformedModCompileOnly(deobf("https://forum.industrial-craft.net/core/attachment/4316-advancedsolarpanel-1-7-10-3-5-1-jar/"))
transformedModCompileOnly(rfg.deobf("curse.maven:candycraft-251118:2330488"))

devOnlyNonPublishable(deobf("https://github.com/makamys/CoreTweaks/releases/download/0.3.3.2/CoreTweaks-1.7.10-0.3.3.2+nomixin.jar"))
transformedModCompileOnly(deobf("https://github.com/makamys/CoreTweaks/releases/download/0.3.3.2/CoreTweaks-1.7.10-0.3.3.2+nomixin.jar"))
}

// Replace when RFG support deobfuscation from notch mappings
Expand Down
49 changes: 43 additions & 6 deletions src/main/java/com/mitchej123/hodgepodge/commands/DebugCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.mitchej123.hodgepodge.config.TweaksConfig;
import com.mitchej123.hodgepodge.mixins.interfaces.IPauseWhenEmpty;
import com.mitchej123.hodgepodge.util.AnchorAlarm;

public class DebugCommand extends CommandBase {
Expand All @@ -26,28 +28,31 @@ public String getCommandName() {

@Override
public String getCommandUsage(ICommandSender sender) {
return "Usage: hp <subcommand>. Valid subcommands are: toggle, anchor, randomNbt.";
return "Usage: hp <subcommand>. Valid subcommands are: toggle, anchor, randomNbt, pauseWhenEmpty.";
}

private void printHelp(ICommandSender sender) {
sender.addChatMessage(new ChatComponentText("Usage: hp <toggle|anchor|randomNbt>"));
sender.addChatMessage(new ChatComponentText("Usage: hp <toggle|anchor|randomNbt|pauseWhenEmpty>"));
sender.addChatMessage(new ChatComponentText("\"toggle anchordebug\" - toggles RC anchor debugging"));
sender.addChatMessage(
new ChatComponentText(
"\"anchor list [player]\" - list RC anchors placed by the player (empty for current player)"));
sender.addChatMessage(
new ChatComponentText(
"\"randomNbt [bytes]\" - adds a random byte array of the given size to the held item"));
sender.addChatMessage(
new ChatComponentText(
"\"pauseWhenEmpty [seconds]\" - sets the time the server will wait before pausing when no players are online; 0 to disable"));
}

@Override
public List<String> addTabCompletionOptions(ICommandSender sender, String[] ss) {
List<String> l = new ArrayList<>();
String test = ss.length == 0 ? "" : ss[0].trim();
if (ss.length == 0 || ss.length == 1
&& (test.isEmpty() || Stream.of("toggle", "anchor", "randomNbt").anyMatch(s -> s.startsWith(test)))) {
Stream.of("toggle", "anchor", "randomNbt").filter(s -> test.isEmpty() || s.startsWith(test))
.forEach(l::add);
if (ss.length == 0 || ss.length == 1 && (test.isEmpty()
|| Stream.of("toggle", "anchor", "randomNbt", "pauseWhenEmpty").anyMatch(s -> s.startsWith(test)))) {
Stream.of("toggle", "anchor", "randomNbt", "pauseWhenEmpty")
.filter(s -> test.isEmpty() || s.startsWith(test)).forEach(l::add);
} else if (test.equals("toggle")) {
String test1 = ss[1].trim();
if (test1.isEmpty() || "anchordebug".startsWith(test1)) l.add("anchordebug");
Expand Down Expand Up @@ -112,6 +117,38 @@ public void processCommand(ICommandSender sender, String[] strings) {
stack.stackTagCompound.setByteArray("DebugJunk", randomData);
player.inventory.inventoryChanged = true;
player.inventoryContainer.detectAndSendChanges();
break;
case "pauseWhenEmpty":
if (!TweaksConfig.pauseWhenEmpty) {
sender.addChatMessage(new ChatComponentText("'pauseWhenEmpty' config option is disabled"));
return;
}
if (strings.length < 2) {
printHelp(sender);
return;
}
final int pauseTimeout = NumberUtils.toInt(strings[1], -1);
if (pauseTimeout < 0) {
printHelp(sender);
return;
}

MinecraftServer server = MinecraftServer.getServer();
if (!server.isDedicatedServer()) {
sender.addChatMessage(
new ChatComponentText("'hp pauseWhenEmpty' only applies to dedicated servers"));
return;
}

if (server instanceof IPauseWhenEmpty p) {
p.setPauseWhenEmptySeconds(pauseTimeout);
sender.addChatMessage(
new ChatComponentText(
String.format(
"Server property 'pause-when-empty-seconds' set to %d",
pauseTimeout)));
}

break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ public class TweaksConfig {
@Config.DefaultInt(900)
public static int autoSaveInterval;

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

@Config.Comment("Reduces water opacity from 3 to 1, to match modern")
@Config.DefaultBoolean(false)
public static boolean useLighterWater;
Expand Down Expand Up @@ -306,5 +310,4 @@ public class TweaksConfig {
@Config.Comment("Avoids droping items on container close, and instead places them in the player inventory. (Inspired from EFR)")
@Config.DefaultBoolean(true)
public static boolean avoidDroppingItemsWhenClosing;

}
7 changes: 7 additions & 0 deletions src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,13 @@ public enum Mixins {
.addMixinClasses("minecraft.server.MixinMinecraftServer_AutoSaveInterval")
.setApplyIf(() -> TweaksConfig.autoSaveInterval != 900)),

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.server.MixinMinecraftServer_PauseWhenEmpty",
"minecraft.server.MixinDedicatedServer_PauseWhenEmpty")
.setApplyIf(() -> TweaksConfig.pauseWhenEmpty)),

LIGHTER_WATER(new Builder("Decreases water opacity from 3 to 1, like in modern").setPhase(Phase.EARLY)
.setSide(Side.BOTH).addTargetedMod(TargetedMod.VANILLA).addMixinClasses("minecraft.MixinBlock_LighterWater")
.setApplyIf(() -> TweaksConfig.useLighterWater)),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.mitchej123.hodgepodge.mixins.early.minecraft.server;

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 com.mitchej123.hodgepodge.mixins.interfaces.IPauseWhenEmpty;

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

@Shadow
private PropertyManager settings;

@Unique
private int hodgepodge$pauseWhenEmptySeconds = 0;

@Override
public int getPauseWhenEmptySeconds() {
return hodgepodge$pauseWhenEmptySeconds;
}

@Override
public void setPauseWhenEmptySeconds(int value) {
value = Math.max(value, 0);
hodgepodge$pauseWhenEmptySeconds = value;

settings.setProperty("pause-when-empty-seconds", hodgepodge$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 hodgepodge$setupServer(CallbackInfoReturnable<Boolean> cir) {
hodgepodge$pauseWhenEmptySeconds = settings.getIntProperty("pause-when-empty-seconds", 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.mitchej123.hodgepodge.mixins.early.minecraft.server;

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 com.mitchej123.hodgepodge.Common;
import com.mitchej123.hodgepodge.mixins.interfaces.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();

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

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

if (hodgepodge$emptyTicks >= pauseTicks) {
if (!hodgepodge$wasPaused) {
Common.log
.info("Server empty for {} seconds, saving and pausing", p.getPauseWhenEmptySeconds());
this.serverConfigManager.saveAllPlayerData();
this.saveAllWorlds(true);
hodgepodge$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();
} else if (hodgepodge$wasPaused) {
Common.log.info("Resuming server");
hodgepodge$wasPaused = false;
}
} else if (hodgepodge$wasPaused) {
Common.log.info("Resuming server");
hodgepodge$wasPaused = false;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.mitchej123.hodgepodge.mixins.interfaces;

public interface IPauseWhenEmpty {

int getPauseWhenEmptySeconds();

void setPauseWhenEmptySeconds(int value);
}

0 comments on commit 6aaff70

Please sign in to comment.