Skip to content

Commit 7dd7956

Browse files
ScribbleScribble
authored andcommitted
Added savestate command for #112
1 parent 3e8b068 commit 7dd7956

File tree

7 files changed

+212
-21
lines changed

7 files changed

+212
-21
lines changed

src/main/java/de/scribble/lp/tasmod/TASmod.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import de.scribble.lp.tasmod.commands.recording.CommandRecord;
1616
import de.scribble.lp.tasmod.commands.savetas.CommandSaveTAS;
1717
import de.scribble.lp.tasmod.commands.tutorial.CommandPlaybacktutorial;
18+
import de.scribble.lp.tasmod.savestates.server.SavestateCommand;
1819
import de.scribble.lp.tasmod.savestates.server.SavestateHandler;
1920
import de.scribble.lp.tasmod.savestates.server.SavestateTrackerFile;
2021
import de.scribble.lp.tasmod.tickratechanger.CommandTickrate;
@@ -102,6 +103,7 @@ public void serverStart(FMLServerStartingEvent ev) {
102103
ev.registerServerCommand(new CommandPlaybacktutorial());
103104
ev.registerServerCommand(new CommandFolder());
104105
ev.registerServerCommand(new CommandClearInputs());
106+
ev.registerServerCommand(new SavestateCommand());
105107

106108
// Save Loadstate Count
107109
File savestateDirectory = new File(serverInstance.getDataDirectory() + File.separator + "saves" + File.separator + "savestates" + File.separator);

src/main/java/de/scribble/lp/tasmod/mixin/MixinMinecraftServer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public long modifyMSPT(long fiftyLong) {
3737
@Redirect(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;tick()V", ordinal = 1))
3838
public void redirectTick(MinecraftServer server) {
3939
this.tick();
40-
if (SavestateHandler.state == SavestateState.WASLOADING) {
41-
SavestateHandler.state = SavestateState.NONE;
40+
if (TASmod.savestateHandler.state == SavestateState.WASLOADING) {
41+
TASmod.savestateHandler.state = SavestateState.NONE;
4242
SavestateHandler.playerLoadSavestateEventServer();
4343
}
4444

src/main/java/de/scribble/lp/tasmod/savestates/server/LoadstatePacketHandler.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ public IMessage onMessage(LoadstatePacket message, MessageContext ctx) {
2626
TASmod.savestateHandler.loadState();
2727
} catch (LoadstateException e) {
2828
player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to load a savestate: "+e.getMessage()));
29-
3029
} catch (Exception e) {
3130
player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to load a savestate: "+e.getCause().toString()));
3231
e.printStackTrace();
3332
} finally {
34-
SavestateHandler.state=SavestateState.NONE;
33+
TASmod.savestateHandler.state=SavestateState.NONE;
3534
}
3635
});
3736
}else {
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package de.scribble.lp.tasmod.savestates.server;
2+
3+
import java.io.IOException;
4+
import java.util.List;
5+
6+
import de.scribble.lp.tasmod.TASmod;
7+
import de.scribble.lp.tasmod.savestates.server.exceptions.LoadstateException;
8+
import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateDeleteException;
9+
import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateException;
10+
import net.minecraft.command.CommandBase;
11+
import net.minecraft.command.CommandException;
12+
import net.minecraft.command.ICommandSender;
13+
import net.minecraft.server.MinecraftServer;
14+
import net.minecraft.util.math.BlockPos;
15+
import net.minecraft.util.text.TextComponentString;
16+
17+
public class SavestateCommand extends CommandBase {
18+
19+
@Override
20+
public String getName() {
21+
return "savestate";
22+
}
23+
24+
@Override
25+
public String getUsage(ICommandSender sender) {
26+
return "/savestate <save|load|delete|info> [index]";
27+
}
28+
29+
@Override
30+
public int getRequiredPermissionLevel() {
31+
return 2;
32+
}
33+
34+
@Override
35+
public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
36+
if (args.length == 0) {
37+
int currentIndex = TASmod.savestateHandler.getCurrentIndex();
38+
sender.sendMessage(new TextComponentString(String.format("The current savestate index is %s", currentIndex)));
39+
sender.sendMessage(new TextComponentString(String.format("Available indexes are%s", TASmod.savestateHandler.getIndexesAsString())));
40+
sender.sendMessage(new TextComponentString(" "));
41+
sender.sendMessage(new TextComponentString("/savestate <save|load|delete|info> [index]"));
42+
sender.sendMessage(new TextComponentString("/savestate save - Make a savestate at the next index"));
43+
sender.sendMessage(new TextComponentString("/savestate save <index> - Make a savestate at the specified index"));
44+
sender.sendMessage(new TextComponentString("/savestate load - Load the savestate at the current index"));
45+
sender.sendMessage(new TextComponentString("/savestate load <index> - Load the savestate at the specified index"));
46+
sender.sendMessage(new TextComponentString("/savestate delete <index> - Delete the savestate at the specified index"));
47+
sender.sendMessage(new TextComponentString("/savestate delete <from> <to> - Delete the savestates from the first to the second index"));
48+
sender.sendMessage(new TextComponentString(""));
49+
sender.sendMessage(new TextComponentString("Instead of <index> you can use ~ to specify an index relative to the current one e.g. ~-1 will load " + (currentIndex - 1)));
50+
} else if (args.length >= 1) {
51+
if ("save".equals(args[0])) {
52+
if (args.length == 1) {
53+
try {
54+
TASmod.savestateHandler.saveState();
55+
} catch (SavestateException e) {
56+
throw new CommandException(e.getMessage(), new Object[] {});
57+
} catch (IOException e) {
58+
e.printStackTrace();
59+
throw new CommandException(e.getMessage(), new Object[] {});
60+
} finally {
61+
TASmod.savestateHandler.state = SavestateState.NONE;
62+
}
63+
} else if (args.length == 2) {
64+
try {
65+
TASmod.savestateHandler.saveState(processIndex(args[1]));
66+
} catch (SavestateException e) {
67+
throw new CommandException(e.getMessage(), new Object[] {});
68+
} catch (IOException e) {
69+
e.printStackTrace();
70+
throw new CommandException(e.getMessage(), new Object[] {});
71+
} finally {
72+
TASmod.savestateHandler.state = SavestateState.NONE;
73+
}
74+
} else {
75+
throw new CommandException("Too many arguments!", new Object[] {});
76+
}
77+
} else if ("load".equals(args[0])) {
78+
if (args.length == 1) {
79+
try {
80+
TASmod.savestateHandler.loadState();
81+
} catch (LoadstateException e) {
82+
throw new CommandException(e.getMessage(), new Object[] {});
83+
} catch (IOException e) {
84+
e.printStackTrace();
85+
throw new CommandException(e.getMessage(), new Object[] {});
86+
} finally {
87+
TASmod.savestateHandler.state = SavestateState.NONE;
88+
}
89+
} else if (args.length == 2) {
90+
try {
91+
TASmod.savestateHandler.loadState(processIndex(args[1]));
92+
} catch (LoadstateException e) {
93+
throw new CommandException(e.getMessage(), new Object[] {});
94+
} catch (IOException e) {
95+
e.printStackTrace();
96+
throw new CommandException(e.getMessage(), new Object[] {});
97+
} finally {
98+
TASmod.savestateHandler.state = SavestateState.NONE;
99+
}
100+
} else {
101+
throw new CommandException("Too many arguments!", new Object[] {});
102+
}
103+
} else if ("delete".equals(args[0])) {
104+
if (args.length == 2) {
105+
try {
106+
TASmod.savestateHandler.deleteIndex(processIndex(args[1]));
107+
} catch (SavestateDeleteException e) {
108+
throw new CommandException(e.getMessage(), new Object[] {});
109+
}
110+
} else if (args.length == 3) {
111+
try {
112+
TASmod.savestateHandler.deleteIndex(processIndex(args[1]), processIndex(args[2]));
113+
} catch (SavestateDeleteException e) {
114+
throw new CommandException(e.getMessage(), new Object[] {});
115+
}
116+
} else {
117+
throw new CommandException("Too many arguments!", new Object[] {});
118+
}
119+
} else if ("info".equals(args[0])) {
120+
sender.sendMessage(new TextComponentString(String.format("The current savestate index is %s", TASmod.savestateHandler.getCurrentIndex())));
121+
sender.sendMessage(new TextComponentString(String.format("Available indexes are%s", TASmod.savestateHandler.getIndexesAsString())));
122+
}
123+
}
124+
}
125+
126+
private int processIndex(String arg) throws CommandException {
127+
if ("~".equals(arg)) {
128+
return TASmod.savestateHandler.getCurrentIndex();
129+
} else if (arg.matches("~-?\\d")) {
130+
arg = arg.replace("~", "");
131+
int i = Integer.parseInt(arg);
132+
return TASmod.savestateHandler.getCurrentIndex() + i;
133+
} else {
134+
int i = 0;
135+
try {
136+
i = Integer.parseInt(arg);
137+
} catch (NumberFormatException e) {
138+
throw new CommandException("The specified index is not a number: %s", arg);
139+
}
140+
return i;
141+
}
142+
}
143+
144+
@Override
145+
public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, BlockPos targetPos) {
146+
if (args.length == 1) {
147+
return getListOfStringsMatchingLastWord(args, new String[] { "save", "load", "delete", "info" });
148+
} else if (args.length == 2 && !"info".equals(args[0])) {
149+
sender.sendMessage(new TextComponentString("Available indexes: " + TASmod.savestateHandler.getIndexesAsString()));
150+
}
151+
return super.getTabCompletions(server, sender, args, targetPos);
152+
}
153+
}

src/main/java/de/scribble/lp/tasmod/savestates/server/SavestateHandler.java

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import de.scribble.lp.tasmod.savestates.client.InputSavestatesPacket;
1919
import de.scribble.lp.tasmod.savestates.server.chunkloading.SavestatesChunkControl;
2020
import de.scribble.lp.tasmod.savestates.server.exceptions.LoadstateException;
21+
import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateDeleteException;
2122
import de.scribble.lp.tasmod.savestates.server.exceptions.SavestateException;
2223
import de.scribble.lp.tasmod.savestates.server.motion.ClientMotionServer;
2324
import de.scribble.lp.tasmod.savestates.server.playerloading.SavestatePlayerLoading;
@@ -50,7 +51,7 @@ public class SavestateHandler {
5051
private MinecraftServer server;
5152
private File savestateDirectory;
5253

53-
public static SavestateState state = SavestateState.NONE;
54+
public SavestateState state = SavestateState.NONE;
5455

5556
public SavestateHandler(MinecraftServer server) {
5657
this.server = server;
@@ -66,8 +67,9 @@ public SavestateHandler(MinecraftServer server) {
6667
* <br>
6768
* Side: Server
6869
*
69-
* @param savestateIndex The index where the mod will save the savestate. -1 if
70-
* it should load the latest
70+
* @param savestateIndex The index where the mod will save the savestate.
71+
* index<=0 if it should load the next from the
72+
* currentindex
7173
* @throws SavestateException
7274
* @throws IOException
7375
*/
@@ -98,7 +100,7 @@ public void saveState(int savestateIndex) throws SavestateException, IOException
98100
server.getPlayerList().saveAllPlayerData();
99101
server.saveAllWorlds(true);
100102

101-
if (savestateIndex < 0) {
103+
if (savestateIndex <= 0) {
102104
setCurrentIndex(currentIndex + 1);
103105
} else {
104106
setCurrentIndex(savestateIndex);
@@ -135,6 +137,9 @@ public void saveState(int savestateIndex) throws SavestateException, IOException
135137

136138
saveCurrentIndexToFile();
137139

140+
// Send a notification that the savestate has been loaded
141+
server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + currentIndex + " saved"));
142+
138143
// Close the GuiSavestateScreen on the client
139144
CommonProxy.NETWORK.sendToAll(new SavestatePacket());
140145

@@ -234,6 +239,9 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException
234239
if (savestateIndex < 0) {
235240
setCurrentIndex(currentIndex);
236241
} else {
242+
if (!get(savestateIndex).exists()) {
243+
throw new LoadstateException("The savestate to load doesn't exist");
244+
}
237245
setCurrentIndex(savestateIndex);
238246
}
239247

@@ -242,10 +250,6 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException
242250
File currentfolder = new File(savestateDirectory, ".." + File.separator + worldname);
243251
File targetfolder = get(currentIndex);
244252

245-
if (!targetfolder.exists()) {
246-
throw new LoadstateException("The savestate to load doesn't exist");
247-
}
248-
249253
// Load savestate on the client
250254
CommonProxy.NETWORK.sendToAll(new InputSavestatesPacket(false, getSavestateNameWithIndex(currentIndex)));
251255

@@ -287,7 +291,7 @@ public void loadState(int savestateIndex) throws LoadstateException, IOException
287291
saveCurrentIndexToFile();
288292

289293
// Send a notification that the savestate has been loaded
290-
server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate loaded"));
294+
server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + currentIndex + " loaded"));
291295

292296
WorldServer[] worlds = DimensionManager.getWorlds();
293297

@@ -415,14 +419,14 @@ public boolean accept(File pathname) {
415419
}
416420
Collections.sort(indexList);
417421
if (indexList.isEmpty()) {
418-
indexList.add(1);
422+
indexList.add(0);
419423
}
420424
nextFreeIndex = indexList.get(indexList.size() - 1);
421425
}
422426

423-
public void deleteIndex(int index) {
424-
if (index < 0) {
425-
return;
427+
public void deleteIndex(int index) throws SavestateDeleteException {
428+
if (index <= 0) {
429+
throw new SavestateDeleteException("Cannot delete the indexes below or exactly 0: " + index);
426430
}
427431
File toDelete = get(index);
428432
if (toDelete.exists()) {
@@ -433,11 +437,20 @@ public void deleteIndex(int index) {
433437
}
434438
}
435439
refresh();
440+
if(!indexList.contains(currentIndex)) {
441+
setCurrentIndex(nextFreeIndex);
442+
}
443+
// Send a notification that the savestate has been deleted
444+
server.getPlayerList().sendMessage(new TextComponentString(TextFormatting.GREEN + "Savestate " + index + " deleted"));
436445
}
437446

438-
public List<Integer> getIndexes() {
447+
public String getIndexesAsString() {
439448
refresh();
440-
return indexList;
449+
String out = "";
450+
for (int i : indexList) {
451+
out = out.concat(" " + i + ",");
452+
}
453+
return out;
441454
}
442455

443456
private File get(int index) {
@@ -484,7 +497,6 @@ public void loadCurrentIndexFromFile() {
484497
}
485498
}
486499
setCurrentIndex(index);
487-
;
488500
}
489501

490502
private void setCurrentIndex(int index) {
@@ -500,6 +512,10 @@ private String getSavestateNameWithIndex(int index) {
500512
return server.getFolderName() + "-Savestate" + index;
501513
}
502514

515+
public int getCurrentIndex() {
516+
return currentIndex;
517+
}
518+
503519
/**
504520
* Event, that gets executed after a loadstate operation was carried out, get's
505521
* called on the server side
@@ -524,4 +540,13 @@ public void loadState() throws LoadstateException, IOException {
524540
public void saveState() throws SavestateException, IOException {
525541
saveState(-1);
526542
}
543+
544+
public void deleteIndex(int from, int to) throws SavestateDeleteException {
545+
if (from >= to) {
546+
throw new SavestateDeleteException("The 'from-index' is smaller or equal to the 'to-index'");
547+
}
548+
for (int i = from; i < to; i++) {
549+
deleteIndex(i);
550+
}
551+
}
527552
}

src/main/java/de/scribble/lp/tasmod/savestates/server/SavestatePacketHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public IMessage onMessage(SavestatePacket message, MessageContext ctx) {
3939
e.printStackTrace();
4040
player.sendMessage(new TextComponentString(TextFormatting.RED+"Failed to create a savestate: "+ e.getCause().toString()));
4141
} finally {
42-
SavestateHandler.state=SavestateState.NONE;
42+
TASmod.savestateHandler.state=SavestateState.NONE;
4343
}
4444
});
4545
}else {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package de.scribble.lp.tasmod.savestates.server.exceptions;
2+
3+
public class SavestateDeleteException extends Exception {
4+
/**
5+
*
6+
*/
7+
private static final long serialVersionUID = -3117656644168896404L;
8+
9+
public SavestateDeleteException(String s) {
10+
super(s);
11+
}
12+
}

0 commit comments

Comments
 (0)