Add in storage, detection and validation of the ItemID array between client and server
and also for world saves. May help with item configuration issues.
This commit is contained in:
parent
e6d66322fe
commit
f4070ff625
21 changed files with 705 additions and 54 deletions
|
@ -39,6 +39,7 @@ import net.minecraft.client.WorldClient;
|
|||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.MapDifference;
|
||||
|
||||
import cpw.mods.fml.client.modloader.ModLoaderClientHelper;
|
||||
import cpw.mods.fml.client.registry.KeyBindingRegistry;
|
||||
|
@ -61,8 +62,10 @@ import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
|||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.network.ModMissingPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
import cpw.mods.fml.common.registry.IThrowableEntity;
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
import cpw.mods.fml.common.registry.LanguageRegistry;
|
||||
|
||||
|
||||
|
@ -113,6 +116,8 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
|
||||
private DuplicateModsFoundException dupesFound;
|
||||
|
||||
private boolean serverShouldBeKilledQuietly;
|
||||
|
||||
/**
|
||||
* Called to start the whole game off
|
||||
*
|
||||
|
@ -404,6 +409,7 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
@Override
|
||||
public void beginServerLoading(MinecraftServer server)
|
||||
{
|
||||
serverShouldBeKilledQuietly = false;
|
||||
// NOOP
|
||||
}
|
||||
|
||||
|
@ -459,4 +465,49 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
{
|
||||
return NetClientHandler.getConnectionCompatibilityLevel();
|
||||
}
|
||||
|
||||
public void warnIDMismatch(MapDifference<Integer, ItemData> idDifferences, boolean mayContinue)
|
||||
{
|
||||
GuiIdMismatchScreen mismatch = new GuiIdMismatchScreen(idDifferences, mayContinue);
|
||||
client.func_71373_a(mismatch);
|
||||
}
|
||||
|
||||
public void callbackIdDifferenceResponse(boolean response)
|
||||
{
|
||||
if (response)
|
||||
{
|
||||
serverShouldBeKilledQuietly = false;
|
||||
GameRegistry.releaseGate(true);
|
||||
client.continueWorldLoading();
|
||||
}
|
||||
else
|
||||
{
|
||||
serverShouldBeKilledQuietly = true;
|
||||
GameRegistry.releaseGate(false);
|
||||
// Reset and clear the client state
|
||||
client.func_71403_a((WorldClient)null);
|
||||
client.func_71373_a(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldServerShouldBeKilledQuietly()
|
||||
{
|
||||
return serverShouldBeKilledQuietly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnectIDMismatch(MapDifference<Integer, ItemData> s, NetHandler toKill, INetworkManager mgr)
|
||||
{
|
||||
// Nuke the connection
|
||||
((NetClientHandler)toKill).func_72553_e();
|
||||
// Stop GuiConnecting
|
||||
GuiConnecting.forceTermination((GuiConnecting)client.field_71462_r);
|
||||
// pulse the network manager queue to clear cruft
|
||||
mgr.func_74428_b();
|
||||
// Nuke the world client
|
||||
client.func_71403_a((WorldClient)null);
|
||||
// Show error screen
|
||||
warnIDMismatch(s, false);
|
||||
}
|
||||
}
|
||||
|
|
87
fml/client/cpw/mods/fml/client/GuiIdMismatchScreen.java
Normal file
87
fml/client/cpw/mods/fml/client/GuiIdMismatchScreen.java
Normal file
|
@ -0,0 +1,87 @@
|
|||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.MapDifference;
|
||||
import com.google.common.collect.MapDifference.ValueDifference;
|
||||
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import net.minecraft.src.GuiButton;
|
||||
import net.minecraft.src.GuiYesNo;
|
||||
import net.minecraft.src.StringTranslate;
|
||||
|
||||
public class GuiIdMismatchScreen extends GuiYesNo {
|
||||
private List<String> missingIds = Lists.newArrayList();
|
||||
private List<String> mismatchedIds = Lists.newArrayList();
|
||||
private boolean allowContinue;
|
||||
|
||||
public GuiIdMismatchScreen(MapDifference<Integer, ItemData> idDifferences, boolean allowContinue)
|
||||
{
|
||||
super(null,"ID mismatch", "Should I continue?", 1);
|
||||
field_73942_a = this;
|
||||
for (Entry<Integer, ItemData> entry : idDifferences.entriesOnlyOnLeft().entrySet())
|
||||
{
|
||||
missingIds.add(String.format("ID %d (ModID: %s, type %s) is missing", entry.getValue().itemId, entry.getValue().modId, entry.getValue().itemType));
|
||||
}
|
||||
for (Entry<Integer, ValueDifference<ItemData>> entry : idDifferences.entriesDiffering().entrySet())
|
||||
{
|
||||
ItemData world = entry.getValue().leftValue();
|
||||
ItemData game = entry.getValue().rightValue();
|
||||
mismatchedIds.add(String.format("ID %d is mismatched. World: (ModID: %s, type %s, ordinal %d) Game (ModID: %s, type %s, ordinal %d)", world.itemId, world.modId, world.itemType, world.ordinal, game.modId, game.itemType, game.ordinal));
|
||||
}
|
||||
this.allowContinue = allowContinue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_73878_a(boolean choice, int p_73878_2_)
|
||||
{
|
||||
FMLClientHandler.instance().callbackIdDifferenceResponse(choice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
if (!allowContinue && field_73887_h.size() == 2)
|
||||
{
|
||||
field_73887_h.remove(0);
|
||||
}
|
||||
int offset = Math.max(85 - missingIds.size() * 10 + mismatchedIds.size() * 30, 10);
|
||||
this.func_73732_a(this.field_73886_k, "Forge Mod Loader has found world ID mismatches", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
for (String s: missingIds) {
|
||||
this.func_73732_a(this.field_73886_k, s, this.field_73880_f / 2, offset, 0xEEEEEE);
|
||||
offset += 10;
|
||||
}
|
||||
for (String s: mismatchedIds) {
|
||||
this.func_73732_a(this.field_73886_k, s, this.field_73880_f / 2, offset, 0xEEEEEE);
|
||||
offset += 10;
|
||||
}
|
||||
offset += 10;
|
||||
if (allowContinue)
|
||||
{
|
||||
this.func_73732_a(this.field_73886_k, "Do you wish to continue loading?", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.func_73732_a(this.field_73886_k, "You cannot connect to this server", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
}
|
||||
// super.super. Grrr
|
||||
for (int var4 = 0; var4 < this.field_73887_h.size(); ++var4)
|
||||
{
|
||||
GuiButton var5 = (GuiButton)this.field_73887_h.get(var4);
|
||||
var5.field_73743_d = Math.min(offset + 10, this.field_73881_g - 20);
|
||||
if (!allowContinue)
|
||||
{
|
||||
var5.field_73746_c = this.field_73880_f / 2 - 75;
|
||||
var5.field_73744_e = StringTranslate.func_74808_a().func_74805_b("gui.done");
|
||||
}
|
||||
var5.func_73737_a(this.field_73882_e, p_73863_1_, p_73863_2_);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import com.google.common.base.Strings;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.MapDifference;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
@ -35,6 +36,7 @@ import com.google.common.collect.Sets;
|
|||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
import cpw.mods.fml.common.registry.TickRegistry;
|
||||
import cpw.mods.fml.server.FMLServerHandler;
|
||||
|
||||
|
@ -427,4 +429,14 @@ public class FMLCommonHandler
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldServerBeKilledQuietly()
|
||||
{
|
||||
return sidedDelegate.shouldServerShouldBeKilledQuietly();
|
||||
}
|
||||
|
||||
public void disconnectIDMismatch(MapDifference<Integer, ItemData> serverDifference, NetHandler toKill, INetworkManager network)
|
||||
{
|
||||
sidedDelegate.disconnectIDMismatch(serverDifference, toKill, network);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ import com.google.common.collect.MapMaker;
|
|||
import com.google.common.collect.Sets;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
|
@ -70,6 +73,9 @@ public class FMLDummyContainer extends DummyModContainer implements WorldAccessC
|
|||
list.func_74742_a(mod);
|
||||
}
|
||||
fmlData.func_74782_a("ModList", list);
|
||||
NBTTagList itemList = new NBTTagList();
|
||||
GameRegistry.writeItemData(itemList);
|
||||
fmlData.func_74782_a("ModItemData", itemList);
|
||||
return fmlData;
|
||||
}
|
||||
|
||||
|
@ -96,5 +102,16 @@ public class FMLDummyContainer extends DummyModContainer implements WorldAccessC
|
|||
}
|
||||
}
|
||||
}
|
||||
if (tag.func_74764_b("ModItemData"))
|
||||
{
|
||||
NBTTagList modList = tag.func_74761_m("ModItemData");
|
||||
Set<ItemData> worldSaveItems = GameRegistry.buildWorldItemData(modList);
|
||||
GameRegistry.validateWorldSave(worldSaveItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameRegistry.validateWorldSave(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,13 @@ import java.util.Random;
|
|||
import net.minecraft.shared.*;
|
||||
|
||||
|
||||
/**
|
||||
* Deprecated without replacement, use vanilla DispenserRegistry code
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public interface IDispenseHandler
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -5,9 +5,13 @@ import java.util.Random;
|
|||
import net.minecraft.shared.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Deprecated without replacement. Use vanilla DispenserRegistry code.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public interface IDispenserHandler
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -2,11 +2,14 @@ package cpw.mods.fml.common;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.MapDifference;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.shared.*;
|
||||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.network.ModMissingPacket;
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
|
||||
public interface IFMLSidedHandler
|
||||
|
@ -38,4 +41,8 @@ public interface IFMLSidedHandler
|
|||
void setClientCompatibilityLevel(byte compatibilityLevel);
|
||||
|
||||
byte getClientCompatibilityLevel();
|
||||
|
||||
boolean shouldServerShouldBeKilledQuietly();
|
||||
|
||||
void disconnectIDMismatch(MapDifference<Integer, ItemData> s, NetHandler toKill, INetworkManager mgr);
|
||||
}
|
||||
|
|
|
@ -721,7 +721,7 @@ public class Loader
|
|||
|
||||
public ModContainer activeModContainer()
|
||||
{
|
||||
return modController.activeContainer();
|
||||
return modController != null ? modController.activeContainer() : null;
|
||||
}
|
||||
|
||||
public boolean isInState(LoaderState state)
|
||||
|
@ -735,7 +735,7 @@ public class Loader
|
|||
}
|
||||
|
||||
public boolean hasReachedState(LoaderState state) {
|
||||
return modController.hasReachedState(state);
|
||||
return modController != null ? modController.hasReachedState(state) : false;
|
||||
}
|
||||
|
||||
public String getMCPVersionString() {
|
||||
|
|
|
@ -31,7 +31,7 @@ import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
|||
public class FMLNetworkHandler
|
||||
{
|
||||
private static final int FML_HASH = Hashing.murmur3_32().hashString("FML").asInt();
|
||||
private static final int PROTOCOL_VERSION = 0x1;
|
||||
private static final int PROTOCOL_VERSION = 0x2;
|
||||
private static final FMLNetworkHandler INSTANCE = new FMLNetworkHandler();
|
||||
|
||||
// List of states for connections from clients to server
|
||||
|
@ -70,7 +70,12 @@ public class FMLNetworkHandler
|
|||
|
||||
private void handleFMLPacket(Packet250CustomPayload packet, INetworkManager network, NetHandler netHandler)
|
||||
{
|
||||
FMLPacket pkt = FMLPacket.readPacket(packet.field_73629_c);
|
||||
FMLPacket pkt = FMLPacket.readPacket(network, packet.field_73629_c);
|
||||
// Part of an incomplete multipart packet
|
||||
if (pkt == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String userName = "";
|
||||
if (netHandler instanceof NetLoginHandler)
|
||||
{
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package cpw.mods.fml.common.network;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.minecraft.shared.*;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.UnsignedBytes;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
@ -18,38 +21,45 @@ public abstract class FMLPacket
|
|||
/**
|
||||
* Opening salutation from the server to the client -> request all mods from the client
|
||||
*/
|
||||
MOD_LIST_REQUEST(ModListRequestPacket.class),
|
||||
MOD_LIST_REQUEST(ModListRequestPacket.class, false),
|
||||
/**
|
||||
* The client responds with the list of mods and versions it has. This is verified by the server.
|
||||
*/
|
||||
MOD_LIST_RESPONSE(ModListResponsePacket.class),
|
||||
MOD_LIST_RESPONSE(ModListResponsePacket.class, false),
|
||||
/**
|
||||
* At which point the server tells the client the mod identifiers for this session.
|
||||
*/
|
||||
MOD_IDENTIFIERS(ModIdentifiersPacket.class),
|
||||
MOD_IDENTIFIERS(ModIdentifiersPacket.class, false),
|
||||
/**
|
||||
* Or, if there is missing stuff, the server tells the client what's missing and drops the connection.
|
||||
*/
|
||||
MOD_MISSING(ModMissingPacket.class),
|
||||
MOD_MISSING(ModMissingPacket.class, false),
|
||||
/**
|
||||
* Open a GUI on the client from the server
|
||||
*/
|
||||
GUIOPEN(OpenGuiPacket.class),
|
||||
GUIOPEN(OpenGuiPacket.class, false),
|
||||
/**
|
||||
* Spawn an entity on the client from the server
|
||||
*/
|
||||
ENTITYSPAWN(EntitySpawnPacket.class),
|
||||
ENTITYSPAWN(EntitySpawnPacket.class, false),
|
||||
/**
|
||||
* Fixes entity location data after spawning
|
||||
*/
|
||||
ENTITYSPAWNADJUSTMENT(EntitySpawnAdjustmentPacket.class);
|
||||
|
||||
ENTITYSPAWNADJUSTMENT(EntitySpawnAdjustmentPacket.class, false),
|
||||
/**
|
||||
* The ID map to send to the client
|
||||
*/
|
||||
MOD_IDMAP(ModIdMapPacket.class, true);
|
||||
|
||||
|
||||
private Class<? extends FMLPacket> packetType;
|
||||
private boolean isMultipart;
|
||||
private ConcurrentMap<INetworkManager, FMLPacket> partTracker;
|
||||
|
||||
private Type(Class<? extends FMLPacket> clazz)
|
||||
private Type(Class<? extends FMLPacket> clazz, boolean isMultipart)
|
||||
{
|
||||
this.packetType = clazz;
|
||||
this.isMultipart = isMultipart;
|
||||
}
|
||||
|
||||
FMLPacket make()
|
||||
|
@ -65,20 +75,64 @@ public abstract class FMLPacket
|
|||
throw new FMLNetworkException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMultipart()
|
||||
{
|
||||
return isMultipart;
|
||||
}
|
||||
|
||||
private FMLPacket findCurrentPart(INetworkManager network)
|
||||
{
|
||||
if (partTracker == null)
|
||||
{
|
||||
partTracker = new MapMaker().weakKeys().weakValues().makeMap();
|
||||
}
|
||||
if (!partTracker.containsKey(network))
|
||||
{
|
||||
partTracker.put(network, make());
|
||||
}
|
||||
return partTracker.get(network);
|
||||
}
|
||||
}
|
||||
|
||||
private Type type;
|
||||
|
||||
public static byte[][] makePacketSet(Type type, Object... data)
|
||||
{
|
||||
if (!type.isMultipart())
|
||||
{
|
||||
return new byte[0][];
|
||||
}
|
||||
byte[] packetData = type.make().generatePacket(data);
|
||||
|
||||
byte[][] chunks = new byte[packetData.length / 32000 + 1][];
|
||||
for (int i = 0; i < packetData.length / 32000 + 1; i++)
|
||||
{
|
||||
int len = Math.min(32000, packetData.length - i* 32000);
|
||||
chunks[i] = Bytes.concat(new byte[] { UnsignedBytes.checkedCast(type.ordinal()), UnsignedBytes.checkedCast(i), UnsignedBytes.checkedCast(chunks.length)}, Ints.toByteArray(len), Arrays.copyOfRange(packetData, i * 32000, len));
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
public static byte[] makePacket(Type type, Object... data)
|
||||
{
|
||||
byte[] packetData = type.make().generatePacket(data);
|
||||
return Bytes.concat(new byte[] { UnsignedBytes.checkedCast(type.ordinal()) }, packetData );
|
||||
}
|
||||
|
||||
public static FMLPacket readPacket(byte[] payload)
|
||||
public static FMLPacket readPacket(INetworkManager network, byte[] payload)
|
||||
{
|
||||
int type = UnsignedBytes.toInt(payload[0]);
|
||||
return Type.values()[type].make().consumePacket(Arrays.copyOfRange(payload, 1, payload.length));
|
||||
Type eType = Type.values()[type];
|
||||
FMLPacket pkt;
|
||||
if (eType.isMultipart())
|
||||
{
|
||||
pkt = eType.findCurrentPart(network);
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = eType.make();
|
||||
}
|
||||
return pkt.consumePacket(Arrays.copyOfRange(payload, 1, payload.length));
|
||||
}
|
||||
|
||||
public FMLPacket(Type type)
|
||||
|
@ -91,8 +145,4 @@ public abstract class FMLPacket
|
|||
public abstract FMLPacket consumePacket(byte[] data);
|
||||
|
||||
public abstract void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName);
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
|
|
99
fml/common/cpw/mods/fml/common/network/ModIdMapPacket.java
Normal file
99
fml/common/cpw/mods/fml/common/network/ModIdMapPacket.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
package cpw.mods.fml.common.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.BitSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.google.common.collect.MapDifference;
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.UnsignedBytes;
|
||||
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
import net.minecraft.src.CompressedStreamTools;
|
||||
import net.minecraft.src.INetworkManager;
|
||||
import net.minecraft.src.NBTTagCompound;
|
||||
import net.minecraft.src.NBTTagList;
|
||||
import net.minecraft.src.NetHandler;
|
||||
import net.minecraft.src.WorldClient;
|
||||
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDMAP;
|
||||
|
||||
public class ModIdMapPacket extends FMLPacket {
|
||||
private byte[][] partials;
|
||||
|
||||
public ModIdMapPacket()
|
||||
{
|
||||
super(MOD_IDMAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
{
|
||||
NBTTagList completeList = (NBTTagList) data[0];
|
||||
NBTTagCompound wrap = new NBTTagCompound();
|
||||
wrap.func_74782_a("List", completeList);
|
||||
try
|
||||
{
|
||||
return CompressedStreamTools.func_74798_a(wrap);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "A critical error writing the id map");
|
||||
throw new FMLNetworkException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput bdi = ByteStreams.newDataInput(data);
|
||||
int chunkIdx = UnsignedBytes.toInt(bdi.readByte());
|
||||
int chunkTotal = UnsignedBytes.toInt(bdi.readByte());
|
||||
int chunkLength = bdi.readInt();
|
||||
if (partials == null)
|
||||
{
|
||||
partials = new byte[chunkTotal][];
|
||||
}
|
||||
partials[chunkIdx] = new byte[chunkLength];
|
||||
bdi.readFully(partials[chunkIdx]);
|
||||
for (int i = 0; i < partials.length; i++)
|
||||
{
|
||||
if (partials[i] == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName)
|
||||
{
|
||||
byte[] allData = Bytes.concat(partials);
|
||||
GameRegistry.initializeServerGate(1);
|
||||
try
|
||||
{
|
||||
NBTTagCompound serverList = CompressedStreamTools.func_74792_a(allData);
|
||||
NBTTagList list = serverList.func_74761_m("List");
|
||||
Set<ItemData> itemData = GameRegistry.buildWorldItemData(list);
|
||||
GameRegistry.validateWorldSave(itemData);
|
||||
MapDifference<Integer, ItemData> serverDifference = GameRegistry.gateWorldLoadingForValidation();
|
||||
if (serverDifference!=null)
|
||||
{
|
||||
FMLCommonHandler.instance().disconnectIDMismatch(serverDifference, netHandler, network);
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package cpw.mods.fml.common.network;
|
|||
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDENTIFIERS;
|
||||
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE;
|
||||
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_MISSING;
|
||||
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDMAP;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -20,6 +21,7 @@ import com.google.common.io.ByteStreams;
|
|||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class ModListResponsePacket extends FMLPacket
|
||||
{
|
||||
|
@ -110,16 +112,25 @@ public class ModListResponsePacket extends FMLPacket
|
|||
FMLLog.info("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods);
|
||||
// Mark this as bad
|
||||
FMLNetworkHandler.setHandlerState((NetLoginHandler) netHandler, FMLNetworkHandler.MISSING_MODS_OR_VERSIONS);
|
||||
pkt.field_73628_b = pkt.field_73629_c.length;
|
||||
network.func_74429_a(pkt);
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt.field_73629_c = FMLPacket.makePacket(MOD_IDENTIFIERS, netHandler);
|
||||
Logger.getLogger("Minecraft").info(String.format("User %s connecting with mods %s", userName, modVersions.keySet()));
|
||||
FMLLog.info("User %s connecting with mods %s", userName, modVersions.keySet());
|
||||
pkt.field_73628_b = pkt.field_73629_c.length;
|
||||
network.func_74429_a(pkt);
|
||||
NBTTagList itemList = new NBTTagList();
|
||||
GameRegistry.writeItemData(itemList);
|
||||
byte[][] registryPackets = FMLPacket.makePacketSet(MOD_IDMAP, itemList);
|
||||
for (int i = 0; i < registryPackets.length; i++)
|
||||
{
|
||||
network.func_74429_a(PacketDispatcher.getPacket("FML", registryPackets[i]));
|
||||
}
|
||||
}
|
||||
|
||||
pkt.field_73628_b = pkt.field_73629_c.length;
|
||||
network.func_74429_a(pkt);
|
||||
// reset the continuation flag - we have completed extra negotiation and the login should complete now
|
||||
NetLoginHandler.func_72531_a((NetLoginHandler) netHandler, true);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package cpw.mods.fml.common.registry;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.minecraft.shared.BiomeGenBase;
|
||||
|
@ -19,10 +21,15 @@ import net.minecraft.shared.TileEntity;
|
|||
import net.minecraft.shared.World;
|
||||
import net.minecraft.shared.WorldType;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.MapDifference;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Sets.SetView;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.ICraftingHandler;
|
||||
|
@ -41,11 +48,10 @@ import cpw.mods.fml.common.ModContainer;
|
|||
public class GameRegistry
|
||||
{
|
||||
private static Multimap<ModContainer, BlockProxy> blockRegistry = ArrayListMultimap.create();
|
||||
private static Multimap<ModContainer, ItemProxy> itemRegistry = ArrayListMultimap.create();
|
||||
private static Set<ItemData> itemRegistry = Sets.newHashSet();
|
||||
private static Set<IWorldGenerator> worldGenerators = Sets.newHashSet();
|
||||
private static List<IFuelHandler> fuelHandlers = Lists.newArrayList();
|
||||
private static List<ICraftingHandler> craftingHandlers = Lists.newArrayList();
|
||||
private static List<IDispenserHandler> dispenserHandlers = Lists.newArrayList();
|
||||
private static List<IPickupNotifier> pickupHandlers = Lists.newArrayList();
|
||||
private static List<IPlayerTracker> playerTrackers = Lists.newArrayList();
|
||||
|
||||
|
@ -83,33 +89,29 @@ public class GameRegistry
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated without replacement. Use vanilla DispenserRegistry code
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
@Deprecated
|
||||
public static void registerDispenserHandler(IDispenserHandler handler)
|
||||
{
|
||||
dispenserHandlers.add(handler);
|
||||
}
|
||||
/**
|
||||
* Register a handler for dispensers
|
||||
* Deprecated without replacement. Use vanilla DispenserRegistry code
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
@Deprecated
|
||||
public static void registerDispenserHandler(final IDispenseHandler handler)
|
||||
{
|
||||
registerDispenserHandler(new IDispenserHandler()
|
||||
{
|
||||
|
||||
@Override
|
||||
public int dispense(int x, int y, int z, int xVelocity, int zVelocity, World world, ItemStack item, Random random, double entX, double entY, double entZ)
|
||||
{
|
||||
return handler.dispense(x, y, z, xVelocity, zVelocity, world, item, random, entX, entY, entZ);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback hook for dispenser activities - if you add a block and want mods to be able
|
||||
* to extend their dispenser related activities to it call this
|
||||
*
|
||||
* Deprecated without replacement, use vanilla DispenserRegistry code
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
|
@ -119,16 +121,9 @@ public class GameRegistry
|
|||
* @param zVelocity
|
||||
* @param item
|
||||
*/
|
||||
@Deprecated
|
||||
public static int tryDispense(World world, int x, int y, int z, int xVelocity, int zVelocity, ItemStack item, Random random, double entX, double entY, double entZ)
|
||||
{
|
||||
for (IDispenserHandler handler : dispenserHandlers)
|
||||
{
|
||||
int dispensed = handler.dispense(x, y, z, xVelocity, zVelocity, world, item, random, entX, entY, entZ);
|
||||
if (dispensed>-1)
|
||||
{
|
||||
return dispensed;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
|
@ -302,4 +297,134 @@ public class GameRegistry
|
|||
for(IPlayerTracker tracker : playerTrackers)
|
||||
tracker.onPlayerRespawn(player);
|
||||
}
|
||||
|
||||
public static void newItemAdded(Item item)
|
||||
{
|
||||
ModContainer mc = Loader.instance().activeModContainer();
|
||||
if (mc == null)
|
||||
{
|
||||
mc = Loader.instance().getMinecraftModContainer();
|
||||
if (Loader.instance().hasReachedState(LoaderState.AVAILABLE))
|
||||
{
|
||||
FMLLog.severe("It appears something has tried to allocate an Item outside of the initialization phase of Minecraft, this could be very bad for your network connectivity.");
|
||||
}
|
||||
}
|
||||
String itemType = item.getClass().getName();
|
||||
itemRegistry.add(new ItemData(item, mc));
|
||||
System.out.printf("Adding item %s(%d) owned by %s\n", item.getClass().getName(), item.field_77779_bT, mc);
|
||||
|
||||
}
|
||||
|
||||
public static void validateWorldSave(Set<ItemData> worldSaveItems)
|
||||
{
|
||||
isSaveValid = true;
|
||||
shouldContinue = true;
|
||||
// allow ourselves to continue if there's no saved data
|
||||
if (worldSaveItems == null)
|
||||
{
|
||||
serverValidationLatch.countDown();
|
||||
try
|
||||
{
|
||||
clientValidationLatch.await();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Function<? super ItemData, Integer> idMapFunction = new Function<ItemData, Integer>() {
|
||||
public Integer apply(ItemData input) {
|
||||
return input.itemId;
|
||||
};
|
||||
};
|
||||
|
||||
Map<Integer,ItemData> worldMap = Maps.uniqueIndex(worldSaveItems,idMapFunction);
|
||||
Map<Integer,ItemData> gameMap = Maps.uniqueIndex(itemRegistry, idMapFunction);
|
||||
difference = Maps.difference(worldMap, gameMap);
|
||||
if (!difference.entriesDiffering().isEmpty() || !difference.entriesOnlyOnLeft().isEmpty())
|
||||
{
|
||||
isSaveValid = false;
|
||||
serverValidationLatch.countDown();
|
||||
}
|
||||
else
|
||||
{
|
||||
isSaveValid = true;
|
||||
serverValidationLatch.countDown();
|
||||
}
|
||||
try
|
||||
{
|
||||
clientValidationLatch.await();
|
||||
if (!shouldContinue)
|
||||
{
|
||||
throw new RuntimeException("This server instance is going to stop abnormally because of a fatal ID mismatch");
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeItemData(NBTTagList itemList)
|
||||
{
|
||||
for (ItemData dat : itemRegistry)
|
||||
{
|
||||
itemList.func_74742_a(dat.toNBT());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the server gate
|
||||
* @param gateCount the countdown amount. If it's 2 we're on the client and the client and server
|
||||
* will wait at the latch. 1 is a server and the server will proceed
|
||||
*/
|
||||
public static void initializeServerGate(int gateCount)
|
||||
{
|
||||
serverValidationLatch = new CountDownLatch(gateCount - 1);
|
||||
clientValidationLatch = new CountDownLatch(gateCount - 1);
|
||||
}
|
||||
|
||||
public static MapDifference<Integer, ItemData> gateWorldLoadingForValidation()
|
||||
{
|
||||
try
|
||||
{
|
||||
serverValidationLatch.await();
|
||||
if (!isSaveValid)
|
||||
{
|
||||
return difference;
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
difference = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static void releaseGate(boolean carryOn)
|
||||
{
|
||||
shouldContinue = carryOn;
|
||||
clientValidationLatch.countDown();
|
||||
}
|
||||
|
||||
public static Set<ItemData> buildWorldItemData(NBTTagList modList)
|
||||
{
|
||||
Set<ItemData> worldSaveItems = Sets.newHashSet();
|
||||
for (int i = 0; i < modList.func_74745_c(); i++)
|
||||
{
|
||||
NBTTagCompound mod = (NBTTagCompound) modList.func_74743_b(i);
|
||||
ItemData dat = new ItemData(mod);
|
||||
worldSaveItems.add(dat);
|
||||
}
|
||||
return worldSaveItems;
|
||||
}
|
||||
|
||||
|
||||
private static CountDownLatch serverValidationLatch;
|
||||
private static CountDownLatch clientValidationLatch;
|
||||
private static MapDifference<Integer, ItemData> difference;
|
||||
private static boolean shouldContinue = true;
|
||||
private static boolean isSaveValid = true;
|
||||
|
||||
}
|
||||
|
|
72
fml/common/cpw/mods/fml/common/registry/ItemData.java
Normal file
72
fml/common/cpw/mods/fml/common/registry/ItemData.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
package cpw.mods.fml.common.registry;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multiset;
|
||||
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
import net.minecraft.src.Item;
|
||||
import net.minecraft.src.NBTTagCompound;
|
||||
|
||||
public class ItemData {
|
||||
|
||||
private static Map<String, Multiset<String>> modOrdinals = Maps.newHashMap();
|
||||
public final String modId;
|
||||
public final String itemType;
|
||||
public final int itemId;
|
||||
public final int ordinal;
|
||||
|
||||
public ItemData(Item item, ModContainer mc)
|
||||
{
|
||||
this.itemId = item.field_77779_bT;
|
||||
this.itemType = item.getClass().getName();
|
||||
this.modId = mc.getModId();
|
||||
if (!modOrdinals.containsKey(mc.getModId()))
|
||||
{
|
||||
modOrdinals.put(mc.getModId(), HashMultiset.<String>create());
|
||||
}
|
||||
this.ordinal = modOrdinals.get(mc.getModId()).add(itemType, 1);
|
||||
}
|
||||
|
||||
public ItemData(NBTTagCompound tag)
|
||||
{
|
||||
this.modId = tag.func_74779_i("ModId");
|
||||
this.itemType = tag.func_74779_i("ItemType");
|
||||
this.itemId = tag.func_74762_e("ItemId");
|
||||
this.ordinal = tag.func_74762_e("ordinal");
|
||||
}
|
||||
|
||||
public NBTTagCompound toNBT()
|
||||
{
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
tag.func_74778_a("ModId", modId);
|
||||
tag.func_74778_a("ItemType", itemType);
|
||||
tag.func_74768_a("ItemId", itemId);
|
||||
tag.func_74768_a("ordinal", ordinal);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(modId, itemType, itemId, ordinal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
ItemData other = (ItemData) obj;
|
||||
return Objects.equal(modId, other.modId) && Objects.equal(itemType, other.itemType) && Objects.equal(itemId, other.itemId) && Objects.equal(ordinal, other.ordinal);
|
||||
}
|
||||
catch (ClassCastException cce)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ package cpw.mods.fml.server;
|
|||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.MapDifference;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.shared.Entity;
|
||||
|
@ -31,6 +32,8 @@ import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
|||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.network.ModMissingPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
import cpw.mods.fml.common.registry.LanguageRegistry;
|
||||
|
||||
/**
|
||||
|
@ -88,6 +91,7 @@ public class FMLServerHandler implements IFMLSidedHandler
|
|||
{
|
||||
Loader.instance().initializeMods();
|
||||
LanguageRegistry.reloadLanguageTable();
|
||||
GameRegistry.initializeServerGate(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -173,4 +177,15 @@ public class FMLServerHandler implements IFMLSidedHandler
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldServerShouldBeKilledQuietly()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void disconnectIDMismatch(MapDifference<Integer, ItemData> s, NetHandler handler, INetworkManager mgr)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,3 +69,5 @@ public qu.bN #FD:EntityVillager/field_70958_bB
|
|||
public qu.bO #FD:EntityVillager/field_70960_bC
|
||||
# GuiButtonMerchant
|
||||
public avu #CL:GuiButtonMerchant
|
||||
|
||||
protected asy.a #FD:GuiYesNo/field_73942_a #guiScreen
|
||||
|
|
|
@ -29,7 +29,29 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
@@ -484,8 +491,10 @@
|
||||
@@ -429,6 +436,10 @@
|
||||
}
|
||||
catch (Throwable var48)
|
||||
{
|
||||
+ if (FMLCommonHandler.instance().shouldServerBeKilledQuietly())
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
var48.printStackTrace();
|
||||
field_71306_a.log(Level.SEVERE, "Encountered an unexpected exception " + var48.getClass().getSimpleName(), var48);
|
||||
CrashReport var2 = null;
|
||||
@@ -459,6 +470,10 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
+ if (FMLCommonHandler.instance().shouldServerBeKilledQuietly())
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
this.func_71260_j();
|
||||
this.field_71316_v = true;
|
||||
}
|
||||
@@ -484,8 +499,10 @@
|
||||
|
||||
public void func_71217_p()
|
||||
{
|
||||
|
@ -40,7 +62,7 @@
|
|||
++this.field_71315_w;
|
||||
|
||||
if (this.field_71295_T)
|
||||
@@ -531,6 +540,7 @@
|
||||
@@ -531,6 +548,7 @@
|
||||
|
||||
this.field_71304_b.func_76319_b();
|
||||
this.field_71304_b.func_76319_b();
|
||||
|
@ -48,7 +70,7 @@
|
|||
}
|
||||
|
||||
public void func_71190_q()
|
||||
@@ -558,6 +568,7 @@
|
||||
@@ -558,6 +576,7 @@
|
||||
}
|
||||
|
||||
this.field_71304_b.func_76320_a("tick");
|
||||
|
@ -56,7 +78,7 @@
|
|||
CrashReport var6;
|
||||
|
||||
try
|
||||
@@ -582,6 +593,7 @@
|
||||
@@ -582,6 +601,7 @@
|
||||
throw new ReportedException(var6);
|
||||
}
|
||||
|
||||
|
@ -64,7 +86,7 @@
|
|||
this.field_71304_b.func_76319_b();
|
||||
this.field_71304_b.func_76320_a("tracker");
|
||||
var4.func_73039_n().func_72788_a();
|
||||
@@ -1150,6 +1162,12 @@
|
||||
@@ -1150,6 +1170,12 @@
|
||||
@SideOnly(Side.SERVER)
|
||||
public static void main(String[] p_main_0_)
|
||||
{
|
||||
|
|
19
fml/patches/common/net/minecraft/src/Item.java.patch
Normal file
19
fml/patches/common/net/minecraft/src/Item.java.patch
Normal file
|
@ -0,0 +1,19 @@
|
|||
--- ../src-base/common/net/minecraft/src/Item.java
|
||||
+++ ../src-work/common/net/minecraft/src/Item.java
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
+import cpw.mods.fml.common.registry.GameRegistry;
|
||||
+
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -187,6 +189,7 @@
|
||||
}
|
||||
|
||||
field_77698_e[256 + p_i3659_1_] = this;
|
||||
+ GameRegistry.newItemAdded(this);
|
||||
}
|
||||
|
||||
public Item func_77665_c(int p_77665_1_)
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
public class SaveHandler implements ISaveHandler, IPlayerFileData
|
||||
{
|
||||
@@ -97,14 +99,16 @@
|
||||
@@ -97,17 +99,23 @@
|
||||
File var1 = new File(this.field_75770_b, "level.dat");
|
||||
NBTTagCompound var2;
|
||||
NBTTagCompound var3;
|
||||
|
@ -28,7 +28,14 @@
|
|||
}
|
||||
catch (Exception var5)
|
||||
{
|
||||
@@ -120,7 +124,9 @@
|
||||
+ if (FMLCommonHandler.instance().shouldServerBeKilledQuietly())
|
||||
+ {
|
||||
+ throw (RuntimeException)var5;
|
||||
+ }
|
||||
var5.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -120,7 +128,9 @@
|
||||
{
|
||||
var2 = CompressedStreamTools.func_74796_a(new FileInputStream(var1));
|
||||
var3 = var2.func_74775_l("Data");
|
||||
|
@ -39,7 +46,7 @@
|
|||
}
|
||||
catch (Exception var4)
|
||||
{
|
||||
@@ -136,7 +142,7 @@
|
||||
@@ -136,7 +146,7 @@
|
||||
NBTTagCompound var3 = p_75755_1_.func_76082_a(p_75755_2_);
|
||||
NBTTagCompound var4 = new NBTTagCompound();
|
||||
var4.func_74782_a("Data", var3);
|
||||
|
@ -48,7 +55,7 @@
|
|||
try
|
||||
{
|
||||
File var5 = new File(this.field_75770_b, "level.dat_new");
|
||||
@@ -174,7 +180,7 @@
|
||||
@@ -174,7 +184,7 @@
|
||||
NBTTagCompound var2 = p_75761_1_.func_76066_a();
|
||||
NBTTagCompound var3 = new NBTTagCompound();
|
||||
var3.func_74782_a("Data", var2);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
import org.lwjgl.opengl.PixelFormat;
|
||||
import org.lwjgl.util.glu.GLU;
|
||||
+
|
||||
+import com.google.common.collect.MapDifference;
|
||||
+
|
||||
+import cpw.mods.fml.client.FMLClientHandler;
|
||||
+import cpw.mods.fml.common.FMLCommonHandler;
|
||||
+import cpw.mods.fml.common.Side;
|
||||
|
@ -73,7 +75,31 @@
|
|||
this.field_71424_I.func_76319_b();
|
||||
this.field_71423_H = func_71386_F();
|
||||
}
|
||||
@@ -1920,6 +1934,12 @@
|
||||
@@ -1777,8 +1799,23 @@
|
||||
}
|
||||
|
||||
this.field_71413_E.func_77450_a(StatList.field_75936_f, 1);
|
||||
+ GameRegistry.initializeServerGate(2);
|
||||
this.field_71437_Z = new IntegratedServer(this, p_71371_1_, p_71371_2_, p_71371_3_);
|
||||
this.field_71437_Z.func_71256_s();
|
||||
+ MapDifference<Integer, ItemData> idDifferences = GameRegistry.gateWorldLoadingForValidation();
|
||||
+ if (idDifferences!=null)
|
||||
+ {
|
||||
+ FMLClientHandler.instance().warnIDMismatch(idDifferences, true);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ GameRegistry.releaseGate(true);
|
||||
+ continueWorldLoading();
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ public void continueWorldLoading()
|
||||
+ {
|
||||
this.field_71455_al = true;
|
||||
this.field_71461_s.func_73720_a(StatCollector.func_74838_a("menu.loadingLevel"));
|
||||
|
||||
@@ -1993,6 +2030,12 @@
|
||||
|
||||
public static void main(String[] p_main_0_)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
--- ../src-base/minecraft/net/minecraft/src/GuiConnecting.java
|
||||
+++ ../src-work/minecraft/net/minecraft/src/GuiConnecting.java
|
||||
@@ -122,4 +122,10 @@
|
||||
{
|
||||
return p_74251_0_.field_73882_e;
|
||||
}
|
||||
+
|
||||
+ public static void forceTermination(GuiConnecting gui)
|
||||
+ {
|
||||
+ gui.field_74258_b = true;
|
||||
+ gui.field_74259_a = null;
|
||||
+ }
|
||||
}
|
Loading…
Reference in a new issue