Ensure level saving is threadsafe, avoids random loss of levels. (Thanks goodlyay)

This commit is contained in:
UnknownShadow200 2016-06-23 11:32:26 +10:00
parent 85c4ae4199
commit 024cd71945
3 changed files with 32 additions and 21 deletions

View File

@ -110,7 +110,6 @@ namespace MCGalaxy.Commands.CPE {
if (index >= offset) {
count++;
Server.s.Log(col.Fallback.ToString());
const string format = "{4}{0} &{1}({2}){4} - %{1}, falls back to &{3}%{3}.";
Player.SendMessage(p, String.Format(format, col.Name, col.Code, col.Hex(), col.Fallback, Server.DefaultColor), false);

View File

@ -238,6 +238,7 @@ namespace MCGalaxy
public bool bufferblocks = Server.bufferblocks;
internal readonly object queueLock = new object();
readonly object saveLock = new object();
public List<BlockQueue.QueuedBlock> blockqueue = new List<BlockQueue.QueuedBlock>();
private readonly object physThreadLock = new object();
BufferedBlockSender bulkSender;
@ -323,8 +324,7 @@ namespace MCGalaxy
#region IDisposable Members
public void Dispose()
{
public void Dispose() {
Extras.Clear();
liquids.Clear();
leaves.Clear();
@ -333,10 +333,13 @@ namespace MCGalaxy
UndoBuffer.Clear();
blockCache.Clear();
ZoneList.Clear();
lock (queueLock)
blockqueue.Clear();
blocks = null;
CustomBlocks = null;
lock (saveLock) {
blocks = null;
CustomBlocks = null;
}
}
#endregion
@ -559,23 +562,10 @@ namespace MCGalaxy
if (!Directory.Exists("levels/prev")) Directory.CreateDirectory("levels/prev");
if (changed || !File.Exists(path) || Override || (physicschanged && clearPhysics)) {
if (clearPhysics)
ClearPhysics();
if (clearPhysics) ClearPhysics();
if (File.Exists(path)) {
string prevPath = LevelInfo.PrevPath(name);
if (File.Exists(prevPath))
File.Delete(prevPath);
File.Copy(path, prevPath, true);
File.Delete(path);
}
LvlFile.Save(this, path + ".backup");
File.Copy(path + ".backup", path);
SaveSettings(this);
Server.s.Log(string.Format("SAVED: Level \"{0}\". ({1}/{2}/{3})", name, players.Count,
PlayerInfo.Online.Count, Server.players));
changed = false;
lock (saveLock)
SaveCore(path);
} else {
Server.s.Log("Skipping level save for " + name + ".");
}
@ -587,6 +577,24 @@ namespace MCGalaxy
GC.Collect();
GC.WaitForPendingFinalizers();
}
void SaveCore(string path) {
if (blocks == null) return;
if (File.Exists(path)) {
string prevPath = LevelInfo.PrevPath(name);
if (File.Exists(prevPath)) File.Delete(prevPath);
File.Copy(path, prevPath, true);
File.Delete(path);
}
LvlFile.Save(this, path + ".backup");
File.Copy(path + ".backup", path);
SaveSettings(this);
Server.s.Log(string.Format("SAVED: Level \"{0}\". ({1}/{2}/{3})", name, players.Count,
PlayerInfo.Online.Count, Server.players));
changed = false;
}
public int Backup(bool Forced = false, string backupName = "") {
if (!backedup || Forced) {

View File

@ -1198,6 +1198,10 @@ return;
}
}
public void HandleCommands(List<string> cmds) {
}
bool CheckCommand(string cmd) {
if (cmd == "") { SendMessage("No command entered."); return false; }
if (Server.agreetorulesonentry && !agreed && !(cmd == "agree" || cmd == "rules" || cmd == "disagree")) {