SSP Worlds updating from 1.6 will now pop a warning message before loading, and will capture a timestamped

zip file in the minecraft dir before starting to load. Allows for people to test updates.
This commit is contained in:
Christian 2014-01-18 22:25:35 -05:00
parent 189dc35060
commit 44a093e74b
7 changed files with 270 additions and 9 deletions

View file

@ -0,0 +1,18 @@
--- ../src-base/minecraft/net/minecraft/client/gui/GuiSelectWorld.java
+++ ../src-work/minecraft/net/minecraft/client/gui/GuiSelectWorld.java
@@ -1,5 +1,6 @@
package net.minecraft.client.gui;
+import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.text.DateFormat;
@@ -179,7 +180,7 @@
if (this.field_146297_k.func_71359_d().func_90033_f(s))
{
- this.field_146297_k.func_71371_a(s, s1, (WorldSettings)null);
+ FMLClientHandler.instance().tryLoadExistingWorld(this, s, s1);
}
}
}

View file

@ -1,16 +1,18 @@
package cpw.mods.fml.client; package cpw.mods.fml.client;
import java.util.Map;
public class ExtendedServerListData { public class ExtendedServerListData {
public final String type; public final String type;
public final boolean isCompatible; public final boolean isCompatible;
public final int modCount; public final Map<String,String> modData;
public final boolean isBlocked; public final boolean isBlocked;
public ExtendedServerListData(String type, boolean isCompatible, int modCount, boolean isBlocked) public ExtendedServerListData(String type, boolean isCompatible, Map<String,String> modData, boolean isBlocked)
{ {
this.type = type; this.type = type;
this.isCompatible = isCompatible; this.isCompatible = isCompatible;
this.modCount = modCount; this.modData = modData;
this.isBlocked = isBlocked; this.isBlocked = isBlocked;
} }
} }

View file

@ -12,6 +12,8 @@
*/ */
package cpw.mods.fml.client; package cpw.mods.fml.client;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -28,6 +30,7 @@ import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiIngameMenu; import net.minecraft.client.gui.GuiIngameMenu;
import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiSelectWorld;
import net.minecraft.client.gui.ServerListEntryNormal; import net.minecraft.client.gui.ServerListEntryNormal;
import net.minecraft.client.multiplayer.GuiConnecting; import net.minecraft.client.multiplayer.GuiConnecting;
import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.ServerData;
@ -42,6 +45,8 @@ import net.minecraft.crash.CrashReport;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.launchwrapper.Launch; import net.minecraft.launchwrapper.Launch;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.INetHandler; import net.minecraft.network.INetHandler;
import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
@ -56,7 +61,10 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap; import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.DummyModContainer; import cpw.mods.fml.common.DummyModContainer;
@ -559,6 +567,46 @@ public class FMLClientHandler implements IFMLSidedHandler
playClientBlock = new CountDownLatch(1); playClientBlock = new CountDownLatch(1);
} }
public File getSavesDir()
{
return new File(client.field_71412_D, "saves");
}
public void tryLoadExistingWorld(GuiSelectWorld selectWorldGUI, String dirName, String saveName)
{
File dir = new File(getSavesDir(), dirName);
NBTTagCompound leveldat;
try
{
leveldat = CompressedStreamTools.func_74796_a(new FileInputStream(new File(dir, "level.dat")));
}
catch (Exception e)
{
try
{
leveldat = CompressedStreamTools.func_74796_a(new FileInputStream(new File(dir, "level.dat_old")));
}
catch (Exception e1)
{
FMLLog.warning("There appears to be a problem loading the save %s, both level files are unreadable.", dirName);
return;
}
}
NBTTagCompound fmlData = leveldat.func_74775_l("FML");
if (fmlData.func_74764_b("ModItemData"))
{
showGuiScreen(new GuiOldSaveLoadConfirm(dirName, saveName, selectWorldGUI));
}
else
{
launchIntegratedServerCallback(dirName, saveName);
}
}
public void launchIntegratedServerCallback(String dirName, String saveName)
{
client.func_71371_a(dirName, saveName, (WorldSettings)null);
}
public void showInGameModOptions(GuiIngameMenu guiIngameMenu) public void showInGameModOptions(GuiIngameMenu guiIngameMenu)
{ {
showGuiScreen(new GuiIngameModOptions(guiIngameMenu)); showGuiScreen(new GuiIngameModOptions(guiIngameMenu));
@ -590,9 +638,16 @@ public class FMLClientHandler implements IFMLSidedHandler
{ {
JsonObject jsonData = extraServerListData.get(originalResponse); JsonObject jsonData = extraServerListData.get(originalResponse);
String type = jsonData.get("type").getAsString(); String type = jsonData.get("type").getAsString();
int modCount = jsonData.get("modList").getAsJsonArray().size(); JsonArray modDataArray = jsonData.get("modList").getAsJsonArray();
boolean moddedClientAllowed = jsonData.has("clientModsAllowed") ? jsonData.get("clientModsAllowed").getAsBoolean() : true; boolean moddedClientAllowed = jsonData.has("clientModsAllowed") ? jsonData.get("clientModsAllowed").getAsBoolean() : true;
serverDataTag.put(data, new ExtendedServerListData(type, true, modCount, !moddedClientAllowed)); Builder<String, String> modListBldr = ImmutableMap.<String,String>builder();
for (JsonElement obj : modDataArray)
{
JsonObject modObj = obj.getAsJsonObject();
modListBldr.put(modObj.get("modid").getAsString(), modObj.get("version").getAsString());
}
serverDataTag.put(data, new ExtendedServerListData(type, true, modListBldr.build(), !moddedClientAllowed));
} }
else else
{ {
@ -602,7 +657,7 @@ public class FMLClientHandler implements IFMLSidedHandler
{ {
moddedClientAllowed = !serverDescription.endsWith(":NOFML§r"); moddedClientAllowed = !serverDescription.endsWith(":NOFML§r");
} }
serverDataTag.put(data, new ExtendedServerListData("VANILLA", false, -1, !moddedClientAllowed)); serverDataTag.put(data, new ExtendedServerListData("VANILLA", false, ImmutableMap.<String,String>of(), !moddedClientAllowed));
} }
startupConnectionData.countDown(); startupConnectionData.countDown();
} }
@ -621,12 +676,12 @@ public class FMLClientHandler implements IFMLSidedHandler
if ("FML".equals(extendedData.type) && extendedData.isCompatible) if ("FML".equals(extendedData.type) && extendedData.isCompatible)
{ {
idx = 0; idx = 0;
tooltip = String.format("Compatible FML modded server\n%d mods present", extendedData.modCount); tooltip = String.format("Compatible FML modded server\n%d mods present", extendedData.modData.size());
} }
else if ("FML".equals(extendedData.type) && !extendedData.isCompatible) else if ("FML".equals(extendedData.type) && !extendedData.isCompatible)
{ {
idx = 16; idx = 16;
tooltip = String.format("Incompatible FML modded server\n%d mods present", extendedData.modCount); tooltip = String.format("Incompatible FML modded server\n%d mods present", extendedData.modData.size());
} }
else if ("BUKKIT".equals(extendedData.type)) else if ("BUKKIT".equals(extendedData.type))
{ {

View file

@ -0,0 +1,55 @@
/*
* Forge Mod Loader
* Copyright (c) 2012-2013 cpw.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* cpw - implementation
*/
package cpw.mods.fml.client;
import java.io.File;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
public class GuiBackupFailed extends GuiScreen
{
private GuiScreen parent;
private File zipName;
public GuiBackupFailed(GuiScreen parent, File zipName)
{
this.parent = parent;
this.zipName = zipName;
}
@SuppressWarnings("unchecked")
@Override
public void func_73866_w_()
{
this.field_146292_n.add(new GuiButton(1, this.field_146294_l / 2 - 75, this.field_146295_m - 38, I18n.func_135052_a("gui.done")));
}
@Override
protected void func_146284_a(GuiButton p_73875_1_)
{
if (p_73875_1_.field_146124_l && p_73875_1_.field_146127_k == 1)
{
FMLClientHandler.instance().showGuiScreen(parent);
}
}
@Override
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
{
this.func_146276_q_();
int offset = Math.max(85 - 2 * 10, 10);
this.func_73732_a(this.field_146289_q, String.format("There was an error saving the archive %s", zipName.getName()), this.field_146294_l / 2, offset, 0xFFFFFF);
offset += 10;
this.func_73732_a(this.field_146289_q, String.format("Please fix the problem and try again"), this.field_146294_l / 2, offset, 0xFFFFFF);
super.func_73863_a(p_73863_1_, p_73863_2_, p_73863_3_);
}
}

View file

@ -0,0 +1,73 @@
package cpw.mods.fml.client;
import java.io.File;
import java.io.IOException;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiLabel;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiSelectWorld;
import net.minecraft.client.gui.GuiYesNo;
import org.apache.logging.log4j.Level;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.ObfuscationReflectionHelper;
import cpw.mods.fml.common.ZipperUtil;
public class GuiOldSaveLoadConfirm extends GuiYesNo {
private String dirName;
private String saveName;
private File zip;
public GuiOldSaveLoadConfirm(String dirName, String saveName, GuiScreen parent)
{
super(parent, "", "", 0);
this.dirName = dirName;
this.saveName = saveName;
this.zip = new File(FMLClientHandler.instance().getClient().field_71412_D,String.format("%s-%2$td%2$tm%2$ty%2$tH%2$tM%2$tS.zip", saveName, System.currentTimeMillis()));
}
@Override
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
{
this.func_146276_q_();
this.func_73732_a(this.field_146289_q, String.format("The world %s contains pre-update modding data", saveName), this.field_146294_l / 2, 50, 16777215);
this.func_73732_a(this.field_146289_q, String.format("There may be problems updating it to this version"), this.field_146294_l / 2, 70, 16777215);
this.func_73732_a(this.field_146289_q, String.format("FML will save a zip to %s", zip.getName()), this.field_146294_l / 2, 90, 16777215);
this.func_73732_a(this.field_146289_q, String.format("Do you wish to continue loading?"), this.field_146294_l / 2, 110, 16777215);
int k;
for (k = 0; k < this.field_146292_n.size(); ++k)
{
((GuiButton)this.field_146292_n.get(k)).func_146112_a(this.field_146297_k, p_73863_1_, p_73863_2_);
}
for (k = 0; k < this.field_146293_o.size(); ++k)
{
((GuiLabel)this.field_146293_o.get(k)).func_146159_a(this.field_146297_k, p_73863_1_, p_73863_2_);
}
}
@Override
protected void func_146284_a(GuiButton p_146284_1_)
{
if (p_146284_1_.field_146127_k == 1)
{
ObfuscationReflectionHelper.setPrivateValue(GuiSelectWorld.class, (GuiSelectWorld)field_146355_a, false, "field_"+"146634_i");
FMLClientHandler.instance().showGuiScreen(field_146355_a);
}
else
{
FMLLog.info("Capturing current state of world %s into file %s", saveName, zip.getAbsolutePath());
try
{
ZipperUtil.zip(new File(FMLClientHandler.instance().getSavesDir(), dirName), zip);
} catch (IOException e)
{
FMLLog.log(Level.WARN, e, "There was a problem saving the backup %s. Please fix and try again", zip.getName());
FMLClientHandler.instance().showGuiScreen(new GuiBackupFailed(field_146355_a, zip));
return;
}
FMLClientHandler.instance().showGuiScreen(null);
FMLClientHandler.instance().launchIntegratedServerCallback(dirName, saveName);
}
}
}

View file

@ -371,7 +371,7 @@ public class FMLCommonHandler
} }
handlerSet.add(handler); handlerSet.add(handler);
Map<String,NBTBase> additionalProperties = Maps.newHashMap(); Map<String,NBTBase> additionalProperties = Maps.newHashMap();
// worldInfo.setAdditionalProperties(additionalProperties); worldInfo.setAdditionalProperties(additionalProperties);
for (ModContainer mc : Loader.instance().getModList()) for (ModContainer mc : Loader.instance().getModList())
{ {
if (mc instanceof InjectedModContainer) if (mc instanceof InjectedModContainer)

View file

@ -0,0 +1,58 @@
package cpw.mods.fml.common;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Deque;
import java.util.LinkedList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import com.google.common.io.Files;
/**
* Copied from http://stackoverflow.com/questions/1399126/java-util-zip-recreating-directory-structure
* because the code looked very tidy and neat. Thanks, McDowell!
*
* @author McDowell
*
*/
public class ZipperUtil {
public static void zip(File directory, File zipfile) throws IOException
{
URI base = directory.toURI();
Deque<File> queue = new LinkedList<File>();
queue.push(directory);
OutputStream out = new FileOutputStream(zipfile);
Closeable res = null;
try
{
ZipOutputStream zout = new ZipOutputStream(out);
res = zout;
while (!queue.isEmpty())
{
directory = queue.pop();
for (File kid : directory.listFiles())
{
String name = base.relativize(kid.toURI()).getPath();
if (kid.isDirectory())
{
queue.push(kid);
name = name.endsWith("/") ? name : name + "/";
zout.putNextEntry(new ZipEntry(name));
} else
{
zout.putNextEntry(new ZipEntry(name));
Files.copy(kid, zout);
zout.closeEntry();
}
}
}
} finally
{
res.close();
}
}
}