Fixing id map generation - should validate correctly now

This commit is contained in:
Christian 2012-12-09 22:24:16 -05:00 committed by LexManos
parent 5e0af1f2cb
commit 1c5b8ecb7b
9 changed files with 180 additions and 146 deletions

View File

@ -64,6 +64,7 @@ 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.GameData;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
import cpw.mods.fml.common.registry.IThrowableEntity;
@ -479,13 +480,13 @@ public class FMLClientHandler implements IFMLSidedHandler
if (response)
{
serverShouldBeKilledQuietly = false;
GameRegistry.releaseGate(true);
GameData.releaseGate(true);
client.continueWorldLoading();
}
else
{
serverShouldBeKilledQuietly = true;
GameRegistry.releaseGate(false);
GameData.releaseGate(false);
// Reset and clear the client state
client.func_71403_a((WorldClient)null);
client.func_71373_a(null);

View File

@ -27,6 +27,7 @@ import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.ItemData;
@ -76,7 +77,7 @@ public class FMLDummyContainer extends DummyModContainer implements WorldAccessC
}
fmlData.func_74782_a("ModList", list);
NBTTagList itemList = new NBTTagList();
GameRegistry.writeItemData(itemList);
GameData.writeItemData(itemList);
fmlData.func_74782_a("ModItemData", itemList);
return fmlData;
}
@ -107,12 +108,12 @@ 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);
Set<ItemData> worldSaveItems = GameData.buildWorldItemData(modList);
GameData.validateWorldSave(worldSaveItems);
}
else
{
GameRegistry.validateWorldSave(null);
GameData.validateWorldSave(null);
}
}

View File

@ -19,6 +19,7 @@ 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.GameData;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.ItemData;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDMAP;
@ -75,14 +76,14 @@ public class ModIdMapPacket extends FMLPacket {
public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName)
{
byte[] allData = Bytes.concat(partials);
GameRegistry.initializeServerGate(1);
GameData.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();
Set<ItemData> itemData = GameData.buildWorldItemData(list);
GameData.validateWorldSave(itemData);
MapDifference<Integer, ItemData> serverDifference = GameData.gateWorldLoadingForValidation();
if (serverDifference!=null)
{
FMLCommonHandler.instance().disconnectIDMismatch(serverDifference, netHandler, network);

View File

@ -23,6 +23,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.GameData;
import cpw.mods.fml.common.registry.GameRegistry;
public class ModListResponsePacket extends FMLPacket
@ -125,7 +126,7 @@ public class ModListResponsePacket extends FMLPacket
pkt.field_73628_b = pkt.field_73629_c.length;
network.func_74429_a(pkt);
NBTTagList itemList = new NBTTagList();
GameRegistry.writeItemData(itemList);
GameData.writeItemData(itemList);
byte[][] registryPackets = FMLPacket.makePacketSet(MOD_IDMAP, itemList);
for (int i = 0; i < registryPackets.length; i++)
{

View File

@ -0,0 +1,157 @@
package cpw.mods.fml.common.registry;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import net.minecraft.src.Item;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.NBTTagList;
import com.google.common.base.Function;
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.ModContainer;
public class GameData {
private static Map<Integer, ItemData> idMap = Maps.newHashMap();
private static CountDownLatch serverValidationLatch;
private static CountDownLatch clientValidationLatch;
private static MapDifference<Integer, ItemData> difference;
private static boolean shouldContinue = true;
private static boolean isSaveValid = true;
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();
ItemData itemData = new ItemData(item, mc);
if (idMap.containsKey(item.field_77779_bT))
{
ItemData id = idMap.get(item.field_77779_bT);
FMLLog.warning("[ItemTracker] The mod %s is attempting to overwrite existing item at %d (%s from %s) with %s", mc.getModId(), id.itemId, id.itemType, id.modId, itemType);
}
idMap.put(item.field_77779_bT, itemData);
FMLLog.fine("[ItemTracker] Adding item %s(%d) owned by %s", item.getClass().getName(), item.field_77779_bT, mc.getModId());
}
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);
difference = Maps.difference(worldMap, idMap);
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 : idMap.values())
{
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;
}
}

View File

@ -51,7 +51,6 @@ import cpw.mods.fml.common.ModContainer;
public class GameRegistry
{
private static Multimap<ModContainer, BlockProxy> blockRegistry = 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();
@ -301,133 +300,4 @@ public class GameRegistry
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;
}

View File

@ -33,6 +33,7 @@ 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.GameData;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.ItemData;
import cpw.mods.fml.common.registry.LanguageRegistry;
@ -92,7 +93,7 @@ public class FMLServerHandler implements IFMLSidedHandler
{
Loader.instance().initializeMods();
LanguageRegistry.reloadLanguageTable();
GameRegistry.initializeServerGate(1);
GameData.initializeServerGate(1);
}
@Override

View File

@ -7,6 +7,7 @@
+import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
+import cpw.mods.fml.common.registry.GameData;
+import cpw.mods.fml.common.registry.GameRegistry;
+import cpw.mods.fml.common.registry.ItemData;
+import cpw.mods.fml.relauncher.ArgsWrapper;
@ -92,19 +93,19 @@
this.field_71413_E.func_77450_a(StatList.field_75936_f, 1);
+
+ GameRegistry.initializeServerGate(2);
+ GameData.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();
+ MapDifference<Integer, ItemData> idDifferences = GameData.gateWorldLoadingForValidation();
+ if (idDifferences!=null)
+ {
+ FMLClientHandler.instance().warnIDMismatch(idDifferences, true);
+ }
+ else
+ {
+ GameRegistry.releaseGate(true);
+ GameData.releaseGate(true);
+ continueWorldLoading();
+ }
+

View File

@ -4,6 +4,7 @@
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
+import cpw.mods.fml.common.registry.GameData;
+import cpw.mods.fml.common.registry.GameRegistry;
+
import java.util.List;
@ -14,7 +15,7 @@
field_77698_e[256 + p_i3659_1_] = this;
+
+ GameRegistry.newItemAdded(this);
+ GameData.newItemAdded(this);
}
public Item func_77665_c(int p_77665_1_)