Registry: Allow ignoring missing mods from the GUI, with confirm+backup
Registry: Add confirm+backup for automated corrupted id table fixup Require the user to confirm loading from a backup level.dat
This commit is contained in:
parent
3eaa002091
commit
407f6f79af
11 changed files with 228 additions and 147 deletions
|
@ -10,7 +10,7 @@
|
|||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
@@ -107,14 +110,22 @@
|
||||
@@ -107,20 +110,29 @@
|
||||
NBTTagCompound nbttagcompound;
|
||||
NBTTagCompound nbttagcompound1;
|
||||
|
||||
|
@ -34,7 +34,14 @@
|
|||
catch (Exception exception1)
|
||||
{
|
||||
exception1.printStackTrace();
|
||||
@@ -129,8 +140,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ FMLCommonHandler.instance().confirmBackupLevelDatUse();
|
||||
file1 = new File(this.field_75770_b, "level.dat_old");
|
||||
|
||||
if (file1.exists())
|
||||
@@ -129,8 +141,14 @@
|
||||
{
|
||||
nbttagcompound = CompressedStreamTools.func_74796_a(new FileInputStream(file1));
|
||||
nbttagcompound1 = nbttagcompound.func_74775_l("Data");
|
||||
|
@ -50,7 +57,7 @@
|
|||
catch (Exception exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
@@ -146,6 +163,8 @@
|
||||
@@ -146,6 +164,8 @@
|
||||
NBTTagCompound nbttagcompound2 = new NBTTagCompound();
|
||||
nbttagcompound2.func_74782_a("Data", nbttagcompound1);
|
||||
|
||||
|
@ -59,7 +66,7 @@
|
|||
try
|
||||
{
|
||||
File file1 = new File(this.field_75770_b, "level.dat_new");
|
||||
@@ -184,6 +203,8 @@
|
||||
@@ -184,6 +204,8 @@
|
||||
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
|
||||
nbttagcompound1.func_74782_a("Data", nbttagcompound);
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -57,6 +55,7 @@ import net.minecraft.network.ServerStatusResponse;
|
|||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.WorldSettings;
|
||||
import net.minecraft.world.storage.ISaveFormat;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
@ -77,7 +76,6 @@ import cpw.mods.fml.client.registry.RenderingRegistry;
|
|||
import cpw.mods.fml.common.DummyModContainer;
|
||||
import cpw.mods.fml.common.DuplicateModsFoundException;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLContainer;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.IFMLSidedHandler;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
|
@ -88,7 +86,6 @@ import cpw.mods.fml.common.ModContainer;
|
|||
import cpw.mods.fml.common.ModMetadata;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
import cpw.mods.fml.common.StartupQuery;
|
||||
import cpw.mods.fml.common.WorldAccessContainer;
|
||||
import cpw.mods.fml.common.WrongMinecraftVersionException;
|
||||
import cpw.mods.fml.common.event.FMLMissingMappingsEvent;
|
||||
import cpw.mods.fml.common.event.FMLMissingMappingsEvent.Action;
|
||||
|
@ -441,6 +438,18 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
{
|
||||
client.displayGuiScreen(new GuiConfirmation(query));
|
||||
}
|
||||
|
||||
if (query.isSynchronous())
|
||||
{
|
||||
while (!(client.currentScreen instanceof GuiMainMenu))
|
||||
{
|
||||
if (Thread.interrupted()) throw new InterruptedException();
|
||||
|
||||
client.loadingScreen.resetProgresAndWorkingMessage("");
|
||||
|
||||
Thread.sleep(50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean handleLoadingScreen(ScaledResolution scaledResolution)
|
||||
|
@ -486,6 +495,12 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
// NOOP
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISaveFormat getSaveFormat()
|
||||
{
|
||||
return client.getSaveLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinecraftServer getServer()
|
||||
{
|
||||
|
@ -634,9 +649,16 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
showGuiScreen(new GuiOldSaveLoadConfirm(dirName, saveName, selectWorldGUI));
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
client.launchIntegratedServer(dirName, saveName, (WorldSettings)null);
|
||||
}
|
||||
catch (StartupQuery.AbortedException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void showInGameModOptions(GuiIngameMenu guiIngameMenu)
|
||||
|
@ -820,19 +842,6 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
}
|
||||
}
|
||||
|
||||
public void setDefaultMissingAction(FMLMissingMappingsEvent.Action action)
|
||||
{
|
||||
this.defaultMissingAction = action;
|
||||
}
|
||||
|
||||
private Action defaultMissingAction = FMLMissingMappingsEvent.Action.FAIL;
|
||||
|
||||
@Override
|
||||
public Action getDefaultMissingAction()
|
||||
{
|
||||
return defaultMissingAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAllowPlayerLogins()
|
||||
{
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* 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.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
public class GuiModItemsMissing extends GuiScreen
|
||||
{
|
||||
private List<String> missingItems;
|
||||
|
||||
public GuiModItemsMissing(List<String> items)
|
||||
{
|
||||
this.missingItems = items;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void initGui()
|
||||
{
|
||||
this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height - 38, I18n.format("gui.done")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton p_73875_1_)
|
||||
{
|
||||
if (p_73875_1_.enabled && p_73875_1_.id == 1)
|
||||
{
|
||||
FMLClientHandler.instance().showGuiScreen(null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.drawDefaultBackground();
|
||||
|
||||
int spaceAvailable = this.height - 38 - 20;
|
||||
int spaceRequired = Math.min(spaceAvailable, 10 + 6 * 10 + missingItems.size());
|
||||
|
||||
int offset = 10 + (spaceAvailable - spaceRequired) / 2; // vertically centered
|
||||
this.drawCenteredString(this.fontRendererObj, "Forge Mod Loader could load this save", this.width / 2, offset, 0xFFFFFF);
|
||||
offset += 20;
|
||||
this.drawCenteredString(this.fontRendererObj, String.format("There are %d unassigned blocks and items in this save", missingItems.size()), this.width / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
this.drawCenteredString(this.fontRendererObj, "You will not be able to load until they are present again", this.width / 2, offset, 0xFFFFFF);
|
||||
offset += 20;
|
||||
|
||||
this.drawCenteredString(this.fontRendererObj, "Missing Blocks/Items:", this.width / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
|
||||
Iterator<String> it = missingItems.iterator();
|
||||
|
||||
while (it.hasNext())
|
||||
{
|
||||
String item = it.next();
|
||||
|
||||
this.drawCenteredString(this.fontRendererObj, item, this.width / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
|
||||
if (offset >= spaceAvailable) break;
|
||||
}
|
||||
|
||||
if (it.hasNext())
|
||||
{
|
||||
this.drawCenteredString(this.fontRendererObj, "...", this.width / 2, offset, 0xFFFFFF);
|
||||
}
|
||||
|
||||
super.drawScreen(p_73863_1_, p_73863_2_, p_73863_3_);
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import org.apache.logging.log4j.Level;
|
|||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
import cpw.mods.fml.common.StartupQuery;
|
||||
import cpw.mods.fml.common.ZipperUtil;
|
||||
|
||||
public class GuiOldSaveLoadConfirm extends GuiYesNo {
|
||||
|
@ -69,7 +70,15 @@ public class GuiOldSaveLoadConfirm extends GuiYesNo {
|
|||
return;
|
||||
}
|
||||
FMLClientHandler.instance().showGuiScreen(null);
|
||||
|
||||
try
|
||||
{
|
||||
mc.launchIntegratedServer(dirName, saveName, (WorldSettings)null);
|
||||
}
|
||||
catch (StartupQuery.AbortedException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ package cpw.mods.fml.common;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
|
@ -30,6 +28,7 @@ import net.minecraft.network.INetHandler;
|
|||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.storage.ISaveFormat;
|
||||
import net.minecraft.world.storage.SaveHandler;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
|
||||
|
@ -285,6 +284,10 @@ public class FMLCommonHandler
|
|||
Loader.instance().serverStopping();
|
||||
}
|
||||
|
||||
public ISaveFormat getSaveFormat() {
|
||||
return sidedDelegate.getSaveFormat();
|
||||
}
|
||||
|
||||
public MinecraftServer getMinecraftServerInstance()
|
||||
{
|
||||
return sidedDelegate.getServer();
|
||||
|
@ -397,6 +400,33 @@ public class FMLCommonHandler
|
|||
}
|
||||
}
|
||||
|
||||
public void confirmBackupLevelDatUse()
|
||||
{
|
||||
// ignore invocations from the world ctor, those are always preceded by another invocation
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
try
|
||||
{
|
||||
if (e.getMethodName().equals("<init>") &&
|
||||
Class.forName(e.getClassName()) == World.class)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e1)
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
String text = "Forge Mod Loader detected that the backup level.dat is being used.\n\n" +
|
||||
"This may happen due to a bug or corruption, continuing can damage\n" +
|
||||
"your world beyond repair or lose data / progress.\n\n" +
|
||||
"It's recommended to create a world backup before continuing.";
|
||||
|
||||
boolean confirmed = StartupQuery.confirm(text);
|
||||
if (!confirmed) StartupQuery.abort();
|
||||
}
|
||||
|
||||
public boolean shouldServerBeKilledQuietly()
|
||||
{
|
||||
if (sidedDelegate == null)
|
||||
|
@ -516,11 +546,6 @@ public class FMLCommonHandler
|
|||
sidedDelegate.fireNetRegistrationEvent(bus(), manager, channelSet, channel, side);
|
||||
}
|
||||
|
||||
public FMLMissingMappingsEvent.Action getDefaultMissingAction()
|
||||
{
|
||||
return sidedDelegate.getDefaultMissingAction();
|
||||
}
|
||||
|
||||
public boolean shouldAllowPlayerLogins()
|
||||
{
|
||||
return sidedDelegate.shouldAllowPlayerLogins();
|
||||
|
|
|
@ -219,7 +219,7 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
|
||||
if (!tag.hasKey("BlockedItemIds")) // no blocked id info -> old 1.7 save
|
||||
{
|
||||
// old 1.7 save potentially affected by the registry mapping bug
|
||||
// old early 1.7 save potentially affected by the registry mapping bug
|
||||
// fix the ids the best we can...
|
||||
GameData.fixBrokenIds(dataList);
|
||||
}
|
||||
|
@ -248,9 +248,9 @@ public class FMLContainer extends DummyModContainer implements WorldAccessContai
|
|||
|
||||
if (failedElements != null && !failedElements.isEmpty())
|
||||
{
|
||||
String text = "Forge Mod Loader could not load this save\n\n" +
|
||||
"There are "+failedElements.size()+" unassigned blocks and items in this save\n"+
|
||||
"You will not be able to load until they are present again\n\n"+
|
||||
String text = "Forge Mod Loader could not load this save.\n\n" +
|
||||
"There are "+failedElements.size()+" unassigned blocks and items in this save.\n" +
|
||||
"You will not be able to load until they are present again.\n\n" +
|
||||
"Missing Blocks/Items:\n";
|
||||
|
||||
for (String s : failedElements) text += s + "\n";
|
||||
|
|
|
@ -14,12 +14,11 @@ package cpw.mods.fml.common;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.minecraft.network.INetHandler;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.storage.ISaveFormat;
|
||||
import cpw.mods.fml.common.event.FMLMissingMappingsEvent;
|
||||
import cpw.mods.fml.common.eventhandler.EventBus;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
@ -40,6 +39,8 @@ public interface IFMLSidedHandler
|
|||
|
||||
void finishServerLoading();
|
||||
|
||||
ISaveFormat getSaveFormat();
|
||||
|
||||
MinecraftServer getServer();
|
||||
|
||||
boolean shouldServerShouldBeKilledQuietly();
|
||||
|
@ -60,7 +61,5 @@ public interface IFMLSidedHandler
|
|||
|
||||
void fireNetRegistrationEvent(EventBus bus, NetworkManager manager, Set<String> channelSet, String channel, Side side);
|
||||
|
||||
FMLMissingMappingsEvent.Action getDefaultMissingAction();
|
||||
|
||||
boolean shouldAllowPlayerLogins();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package cpw.mods.fml.common;
|
|||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
public class StartupQuery {
|
||||
// internal class/functionality, do not use
|
||||
|
||||
|
@ -21,7 +23,9 @@ public class StartupQuery {
|
|||
|
||||
public static void abort()
|
||||
{
|
||||
FMLCommonHandler.instance().getMinecraftServerInstance().initiateShutdown();
|
||||
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
if (server != null) server.initiateShutdown();
|
||||
|
||||
aborted = true; // to abort loading and go back to the main menu
|
||||
throw new AbortedException(); // to halt the server
|
||||
}
|
||||
|
@ -78,6 +82,11 @@ public class StartupQuery {
|
|||
return text;
|
||||
}
|
||||
|
||||
public boolean isSynchronous()
|
||||
{
|
||||
return synchronous;
|
||||
}
|
||||
|
||||
public void finish()
|
||||
{
|
||||
signal.countDown();
|
||||
|
@ -105,15 +114,23 @@ public class StartupQuery {
|
|||
FMLLog.warning("Invalid value for fml.queryResult: %s, expected confirm or cancel", prop);
|
||||
}
|
||||
|
||||
synchronous = false;
|
||||
pending = this; // let the other thread start the query
|
||||
|
||||
// the client will eventually check pending and execute the query
|
||||
// command handling in mc is synchronous, execute the server-side query directly
|
||||
if (FMLCommonHandler.instance().getSide().isServer()) check();
|
||||
// from the integrated server thread: the client will eventually check pending and execute the query
|
||||
// from the client thread: synchronous execution
|
||||
// dedicated server: command handling in mc is synchronous, execute the server-side query directly
|
||||
if (FMLCommonHandler.instance().getSide().isServer() ||
|
||||
FMLCommonHandler.instance().getEffectiveSide().isClient())
|
||||
{
|
||||
synchronous = true;
|
||||
check();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
signal.await();
|
||||
reset();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
|
@ -125,6 +142,7 @@ public class StartupQuery {
|
|||
private String text;
|
||||
private AtomicBoolean result;
|
||||
private CountDownLatch signal = new CountDownLatch(1);
|
||||
private volatile boolean synchronous;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,8 +10,13 @@ import java.util.Deque;
|
|||
import java.util.LinkedList;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
|
||||
/**
|
||||
* Copied from http://stackoverflow.com/questions/1399126/java-util-zip-recreating-directory-structure
|
||||
* because the code looked very tidy and neat. Thanks, McDowell!
|
||||
|
@ -55,4 +60,39 @@ public class ZipperUtil {
|
|||
res.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void backupWorld() throws IOException
|
||||
{
|
||||
String dirName = FMLCommonHandler.instance().getMinecraftServerInstance().getFolderName();
|
||||
String saveName;
|
||||
|
||||
if (FMLCommonHandler.instance().getSide().isClient())
|
||||
{
|
||||
saveName = FMLCommonHandler.instance().getMinecraftServerInstance().getWorldName();
|
||||
}
|
||||
else
|
||||
{
|
||||
saveName = dirName;
|
||||
}
|
||||
|
||||
backupWorld(dirName, saveName);
|
||||
}
|
||||
|
||||
public static void backupWorld(String dirName, String saveName) throws IOException
|
||||
{
|
||||
File dstFolder = FMLCommonHandler.instance().getSaveFormat().getSaveLoader(dirName, false).getWorldDirectory().getParentFile();
|
||||
File zip = new File(dstFolder, String.format("%s-%2$tY%2$tm%2$td-%2$tH%2$tM%2$tS.zip", saveName, System.currentTimeMillis()));
|
||||
|
||||
try
|
||||
{
|
||||
ZipperUtil.zip(new File(dstFolder, dirName), zip);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
FMLLog.log(Level.WARN, e, "World backup failed.");
|
||||
throw e;
|
||||
}
|
||||
|
||||
FMLLog.info("World backup created at %s.", zip.getCanonicalPath());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,11 +41,13 @@ import com.google.common.collect.Maps;
|
|||
import com.google.common.collect.Table;
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.StartupQuery;
|
||||
import cpw.mods.fml.common.ZipperUtil;
|
||||
import cpw.mods.fml.common.event.FMLMissingMappingsEvent;
|
||||
import cpw.mods.fml.common.event.FMLMissingMappingsEvent.MissingMapping;
|
||||
import cpw.mods.fml.common.registry.GameRegistry.Type;
|
||||
|
@ -243,6 +245,7 @@ public class GameData {
|
|||
}
|
||||
|
||||
Set<String> itemsToAllocate = new HashSet<String>();
|
||||
Map<String, Integer> itemsToRelocate = new HashMap<String, Integer>();
|
||||
|
||||
// check all ids occupied by items
|
||||
for (Entry<String, Integer> entry : dataList.entrySet())
|
||||
|
@ -259,18 +262,17 @@ public class GameData {
|
|||
String blockName = '\u0001' + realName;
|
||||
|
||||
if (!dataList.containsKey(blockName) ||
|
||||
!(getMain().iItemRegistry.getRaw(realName) instanceof ItemBlock)) // the slot is occupied by something else and this item is no ItemBlock
|
||||
(getMain().iItemRegistry.getRaw(realName) != null && // don't assume missing items are no ItemBlock
|
||||
!(getMain().iItemRegistry.getRaw(realName) instanceof ItemBlock))) // the slot is occupied by something else and this item is no ItemBlock
|
||||
{
|
||||
// relocate the item later, after all correct ids have been claimed
|
||||
// allocate the item later, after all correct ids have been claimed
|
||||
itemsToAllocate.add(itemName);
|
||||
}
|
||||
else if (dataList.get(blockName) != oldId) // occupied, but this is an ItemBlock for a different block than whatever may use its id
|
||||
{
|
||||
// relocate to the matching block
|
||||
int newId = dataList.get(blockName);
|
||||
entry.setValue(newId);
|
||||
|
||||
FMLLog.warning("Fixed ItemBlock %s not using the id of its block, old id %d, new id %d.", realName, oldId, newId);
|
||||
itemsToRelocate.put(entry.getKey(), newId);
|
||||
}
|
||||
}
|
||||
else // unused id, occupy
|
||||
|
@ -280,6 +282,27 @@ public class GameData {
|
|||
}
|
||||
}
|
||||
|
||||
if (itemsToAllocate.isEmpty() && itemsToRelocate.isEmpty()) return; // nothing to do
|
||||
|
||||
String text = "Forge Mod Loader detected that this save is damaged.\n\n" +
|
||||
"It's likely that an automatic repair can successfully restore\n" +
|
||||
"most of it, except some items which may get swapped with others.\n\n" +
|
||||
"A world backup will be created as a zip file in your saves\n"+
|
||||
"directory automatically.";
|
||||
|
||||
boolean confirmed = StartupQuery.confirm(text);
|
||||
if (!confirmed) StartupQuery.abort();
|
||||
|
||||
try
|
||||
{
|
||||
ZipperUtil.backupWorld();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
StartupQuery.notify("The world backup couldn't be created.\n\n"+e);
|
||||
StartupQuery.abort();
|
||||
}
|
||||
|
||||
for (String itemName : itemsToAllocate)
|
||||
{
|
||||
int oldId = dataList.get(itemName);
|
||||
|
@ -289,6 +312,16 @@ public class GameData {
|
|||
|
||||
FMLLog.warning("Fixed Item %s conflicting with another block/item, old id %d, new id %d.", itemName.substring(1), oldId, newId);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Integer> entry : itemsToRelocate.entrySet())
|
||||
{
|
||||
String itemName = entry.getKey();
|
||||
int newId = entry.getValue();
|
||||
|
||||
int oldId = dataList.put(itemName, newId);
|
||||
|
||||
FMLLog.warning("Fixed ItemBlock %s not using the id of its block, old id %d, new id %d.", itemName.substring(1), oldId, newId);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> injectWorldIDMap(Map<String, Integer> dataList, boolean injectFrozenData, boolean isLocalWorld)
|
||||
|
@ -419,6 +452,7 @@ public class GameData {
|
|||
List<String> failed = Lists.newArrayList();
|
||||
List<String> ignored = Lists.newArrayList();
|
||||
List<String> warned = Lists.newArrayList();
|
||||
List<String> defaulted = Lists.newArrayList();
|
||||
|
||||
for (MissingMapping remap : missedMappings)
|
||||
{
|
||||
|
@ -462,10 +496,9 @@ public class GameData {
|
|||
// block item missing, warn as requested and block the id
|
||||
if (action == FMLMissingMappingsEvent.Action.DEFAULT)
|
||||
{
|
||||
action = FMLCommonHandler.instance().getDefaultMissingAction();
|
||||
defaulted.add(remap.name);
|
||||
}
|
||||
|
||||
if (action == FMLMissingMappingsEvent.Action.IGNORE)
|
||||
else if (action == FMLMissingMappingsEvent.Action.IGNORE)
|
||||
{
|
||||
ignored.add(remap.name);
|
||||
}
|
||||
|
@ -477,14 +510,36 @@ public class GameData {
|
|||
{
|
||||
warned.add(remap.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException(String.format("Invalid default missing id action specified: %s", action.name()));
|
||||
}
|
||||
|
||||
gameData.block(remap.id); // prevent the id from being reused later
|
||||
}
|
||||
}
|
||||
|
||||
if (!defaulted.isEmpty())
|
||||
{
|
||||
String text = "Forge Mod Loader detected missing blocks/items.\n\n" +
|
||||
"There are "+defaulted.size()+" missing blocks and items in this save.\n" +
|
||||
"If you continue the missing blocks/items will get removed.\n" +
|
||||
"A world backup will be automatically created in your saves directory.\n\n" +
|
||||
"Missing Blocks/Items:\n";
|
||||
|
||||
for (String s : defaulted) text += s + "\n";
|
||||
|
||||
boolean confirmed = StartupQuery.confirm(text);
|
||||
if (!confirmed) StartupQuery.abort();
|
||||
|
||||
try
|
||||
{
|
||||
ZipperUtil.backupWorld();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
StartupQuery.notify("The world backup couldn't be created.\n\n"+e);
|
||||
StartupQuery.abort();
|
||||
}
|
||||
|
||||
warned.addAll(defaulted);
|
||||
}
|
||||
if (!failed.isEmpty())
|
||||
{
|
||||
FMLLog.severe("This world contains blocks and items that refuse to be remapped. The world will not be loaded");
|
||||
|
@ -557,6 +612,7 @@ public class GameData {
|
|||
iItemRegistry.set(data.iItemRegistry);
|
||||
availabilityMap.clear();
|
||||
availabilityMap.or(data.availabilityMap);
|
||||
blockedIds.clear();
|
||||
blockedIds.addAll(data.blockedIds);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ package cpw.mods.fml.server;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.minecraft.command.ServerCommand;
|
||||
import net.minecraft.network.INetHandler;
|
||||
|
@ -24,6 +22,7 @@ import net.minecraft.network.NetHandlerPlayServer;
|
|||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.storage.ISaveFormat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
|
@ -33,7 +32,6 @@ import cpw.mods.fml.common.IFMLSidedHandler;
|
|||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.StartupQuery;
|
||||
import cpw.mods.fml.common.WorldAccessContainer;
|
||||
import cpw.mods.fml.common.event.FMLMissingMappingsEvent;
|
||||
import cpw.mods.fml.common.eventhandler.EventBus;
|
||||
import cpw.mods.fml.common.network.FMLNetworkEvent;
|
||||
|
@ -103,6 +101,12 @@ public class FMLServerHandler implements IFMLSidedHandler
|
|||
throw new RuntimeException(message, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISaveFormat getSaveFormat()
|
||||
{
|
||||
return server.getActiveAnvilConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server instance
|
||||
*/
|
||||
|
@ -159,6 +163,8 @@ public class FMLServerHandler implements IFMLSidedHandler
|
|||
"\nAlternatively start the server with -Dfml.queryResult=confirm or -Dfml.queryResult=cancel to preselect the answer.";
|
||||
FMLLog.warning("%s", text);
|
||||
|
||||
if (!query.isSynchronous()) return; // no-op until mc does commands in another thread (if ever)
|
||||
|
||||
boolean done = false;
|
||||
|
||||
while (!done && server.isServerRunning())
|
||||
|
@ -250,11 +256,7 @@ public class FMLServerHandler implements IFMLSidedHandler
|
|||
{
|
||||
bus.post(new FMLNetworkEvent.CustomPacketRegistrationEvent<NetHandlerPlayServer>(manager, channelSet, channel, side, NetHandlerPlayServer.class));
|
||||
}
|
||||
@Override
|
||||
public FMLMissingMappingsEvent.Action getDefaultMissingAction()
|
||||
{
|
||||
return FMLMissingMappingsEvent.Action.valueOf(System.getProperty("fml.missingBlockAction", "FAIL"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAllowPlayerLogins()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue