public Entry(FMLControlledNamespacedRegistry registry) { this.ids = Maps.newHashMap(); this.substitutions = Sets.newHashSet(); this.aliases = Maps.newHashMap(); this.blocked = Sets.newHashSet(); registry.serializeInto(this.ids); registry.serializeSubstitutions(this.substitutions); registry.serializeAliases(this.aliases); if (GameData.getBlockRegistry() == registry || GameData.getItemRegistry() == registry) { this.blocked.addAll(GameData.getMain().blockedIds); } }
public static void freezeData() { FMLLog.fine("Freezing block and item id maps"); getMain().testConsistency(); frozen = new GameData(getMain()); frozen.testConsistency(); }
@Override public ItemStack deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonHelper helper = new JsonHelper(json); String name = helper.getString("name"); int amount = helper.getNullableInteger("amount", 1); int meta = helper.getNullableInteger("meta", 0); return new ItemStack( GameData.getItemRegistry().containsKey(new ResourceLocation(name)) ? GameData.getItemRegistry().getObject(new ResourceLocation(name)) : null, amount, meta); }
public static void rebakeMap() { // System.out.println("Baking OreDictionary:"); stackToId.clear(); for (int id = 0; id < idToStack.size(); id++) { List<ItemStack> ores = idToStack.get(id); if (ores == null) continue; for (ItemStack ore : ores) { // HACK: use the registry name's ID. It is unique and it knows about substitutions ResourceLocation name = ore.getItem().delegate.name(); int hash; if (name == null) { FMLLog.log( Level.DEBUG, "Defaulting unregistered ore dictionary entry for ore dictionary %s: type %s to -1", getOreName(id), ore.getItem().getClass()); hash = -1; } else { hash = GameData.getItemRegistry().getId(name); } if (ore.getItemDamage() != WILDCARD_VALUE) { hash |= ((ore.getItemDamage() + 1) << 16); // +1 so meta 0 is significant } List<Integer> ids = stackToId.get(hash); if (ids == null) { ids = Lists.newArrayList(); stackToId.put(hash, ids); } ids.add(id); // System.out.println(id + " " + getOreName(id) + " " + Integer.toHexString(hash) + " " + // ore); } } }
/** * Gets all the integer ID for the ores that the specified item stack is registered to. If the * item stack is not linked to any ore, this will return an empty array and no new entry will be * created. * * @param stack The item stack of the ore. * @return An array of ids that this ore is registered as. */ public static int[] getOreIDs(ItemStack stack) { if (stack == null || stack.getItem() == null) throw new IllegalArgumentException("Stack can not be null!"); Set<Integer> set = new HashSet<Integer>(); // HACK: use the registry name's ID. It is unique and it knows about substitutions. Fallback to // a -1 value (what Item.getIDForItem would have returned) in the case where the registry is not // aware of the item yet // IT should be noted that -1 will fail the gate further down, if an entry already exists with // value -1 for this name. This is what is broken and being warned about. // APPARENTLY it's quite common to do this. OreDictionary should be considered alongside Recipes // - you can't make them properly until you've registered with the game. ResourceLocation registryName = stack.getItem().delegate.name(); int id; if (registryName == null) { FMLLog.log( Level.DEBUG, "Attempted to find the oreIDs for an unregistered object (%s). This won't work very well.", stack); return new int[0]; } else { id = GameData.getItemRegistry().getId(registryName); } List<Integer> ids = stackToId.get(id); if (ids != null) set.addAll(ids); ids = stackToId.get(id | ((stack.getItemDamage() + 1) << 16)); if (ids != null) set.addAll(ids); Integer[] tmp = set.toArray(new Integer[set.size()]); int[] ret = new int[tmp.length]; for (int x = 0; x < tmp.length; x++) ret[x] = tmp[x]; return ret; }
@Override public JsonElement serialize(ItemStack src, Type typeOfSrc, JsonSerializationContext context) { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty( "name", GameData.getItemRegistry().getNameForObject(src.getItem()).toString()); jsonObject.addProperty("amount", src.stackSize); jsonObject.addProperty("meta", src.getItemDamage()); return jsonObject; }
/** * Registers a ore item into the dictionary. Raises the registerOre function in all registered * handlers. * * @param name The name of the ore * @param ore The ore's ItemStack */ private static void registerOreImpl(String name, ItemStack ore) { if ("Unknown".equals(name)) return; // prevent bad IDs. if (ore == null || ore.getItem() == null) { FMLLog.bigWarning( "Invalid registration attempt for an Ore Dictionary item with name %s has occurred. The registration has been denied to prevent crashes. The mod responsible for the registration needs to correct this.", name); return; // prevent bad ItemStacks. } int oreID = getOreID(name); // HACK: use the registry name's ID. It is unique and it knows about substitutions. Fallback to // a -1 value (what Item.getIDForItem would have returned) in the case where the registry is not // aware of the item yet // IT should be noted that -1 will fail the gate further down, if an entry already exists with // value -1 for this name. This is what is broken and being warned about. // APPARENTLY it's quite common to do this. OreDictionary should be considered alongside Recipes // - you can't make them properly until you've registered with the game. ResourceLocation registryName = ore.getItem().delegate.name(); int hash; if (registryName == null) { FMLLog.bigWarning( "A broken ore dictionary registration with name %s has occurred. It adds an item (type: %s) which is currently unknown to the game registry. This dictionary item can only support a single value when" + " registered with ores like this, and NO I am not going to turn this spam off. Just register your ore dictionary entries after the GameRegistry.\n" + "TO USERS: YES this is a BUG in the mod " + Loader.instance().activeModContainer().getName() + " report it to them!", name, ore.getItem().getClass()); hash = -1; } else { hash = GameData.getItemRegistry().getId(registryName); } if (ore.getItemDamage() != WILDCARD_VALUE) { hash |= ((ore.getItemDamage() + 1) << 16); // +1 so 0 is significant } // Add things to the baked version, and prevent duplicates List<Integer> ids = stackToId.get(hash); if (ids != null && ids.contains(oreID)) return; if (ids == null) { ids = Lists.newArrayList(); stackToId.put(hash, ids); } ids.add(oreID); // Add to the unbaked version ore = ore.copy(); idToStack.get(oreID).add(ore); MinecraftForge.EVENT_BUS.post(new OreRegisterEvent(name, ore)); }
public void initializeMods() { progressBar.step("Initializing mods Phase 2"); // Mod controller should be in the initialization state here modController.distributeStateMessage(LoaderState.INITIALIZATION); progressBar.step("Initializing mods Phase 3"); modController.transition(LoaderState.POSTINITIALIZATION, false); modController.distributeStateMessage(FMLInterModComms.IMCEvent.class); ItemStackHolderInjector.INSTANCE.inject(); modController.distributeStateMessage(LoaderState.POSTINITIALIZATION); progressBar.step("Finishing up"); modController.transition(LoaderState.AVAILABLE, false); modController.distributeStateMessage(LoaderState.AVAILABLE); GameData.freezeData(); FMLLog.info( "Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size() == 1 ? "" : "s"); progressBar.step("Completing Minecraft initialization"); }
public static List<String> processIdRematches( Iterable<MissingMapping> missedMappings, boolean isLocalWorld, GameData gameData, Map<String, Integer[]> remapBlocks, Map<String, Integer[]> remapItems) { List<String> failed = Lists.newArrayList(); List<String> ignored = Lists.newArrayList(); List<String> warned = Lists.newArrayList(); List<String> defaulted = Lists.newArrayList(); for (MissingMapping remap : missedMappings) { FMLMissingMappingsEvent.Action action = remap.getAction(); if (action == FMLMissingMappingsEvent.Action.REMAP) { // block/item re-mapped, finish the registration with the new name/object, but the old id int currId, newId; String newName; if (remap.type == Type.BLOCK) { currId = getMain().iBlockRegistry.getId((Block) remap.getTarget()); newName = getMain().iBlockRegistry.getNameForObject(remap.getTarget()).toString(); FMLLog.fine("The Block %s is being remapped to %s.", remap.name, newName); newId = gameData.registerBlock((Block) remap.getTarget(), newName, remap.id); gameData.iBlockRegistry.addAlias(remap.name, newName); } else { currId = getMain().iItemRegistry.getId((Item) remap.getTarget()); newName = getMain().iItemRegistry.getNameForObject(remap.getTarget()).toString(); FMLLog.fine("The Item %s is being remapped to %s.", remap.name, newName); newId = gameData.registerItem((Item) remap.getTarget(), newName, remap.id); gameData.iItemRegistry.addAlias(remap.name, newName); } if (newId != remap.id) throw new IllegalStateException(); if (currId != newId) { FMLLog.info( "Fixed %s id mismatch %s: %d (init) -> %d (map).", remap.type == Type.BLOCK ? "block" : "item", newName, currId, newId); (remap.type == Type.BLOCK ? remapBlocks : remapItems) .put(newName, new Integer[] {currId, newId}); } } else if (action == FMLMissingMappingsEvent.Action.BLOCKONLY) { // Pulled out specifically so the block doesn't get reassigned a new ID just because it's // Item block has gone away FMLLog.fine( "The ItemBlock %s is no longer present in the game. The residual block will remain", remap.name); } else { // block item missing, warn as requested and block the id if (action == FMLMissingMappingsEvent.Action.DEFAULT) { defaulted.add(remap.name); } else if (action == FMLMissingMappingsEvent.Action.IGNORE) { ignored.add(remap.name); } else if (action == FMLMissingMappingsEvent.Action.FAIL) { failed.add(remap.name); } else if (action == FMLMissingMappingsEvent.Action.WARN) { warned.add(remap.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 { String skip = System.getProperty("fml.doNotBackup"); if (skip == null || !"true".equals(skip)) { ZipperUtil.backupWorld(); } else { for (int x = 0; x < 10; x++) FMLLog.severe("!!!!!!!!!! UPDATING WORLD WITHOUT DOING BACKUP !!!!!!!!!!!!!!!!"); } } 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"); return failed; } if (!warned.isEmpty()) { FMLLog.severe("This world contains block and item mappings that may cause world breakage"); return failed; } else if (!ignored.isEmpty()) { FMLLog.fine("There were %d missing mappings that have been ignored", ignored.size()); } return failed; }
public static List<String> injectSnapshot( GameDataSnapshot snapshot, boolean injectFrozenData, boolean isLocalWorld) { FMLLog.info( "Injecting existing block and item data into this %s instance", FMLCommonHandler.instance().getEffectiveSide().isServer() ? "server" : "client"); Map<String, Integer[]> remapBlocks = Maps.newHashMap(); Map<String, Integer[]> remapItems = Maps.newHashMap(); LinkedHashMap<String, Integer> missingBlocks = new LinkedHashMap<String, Integer>(); LinkedHashMap<String, Integer> missingItems = new LinkedHashMap<String, Integer>(); getMain().testConsistency(); getMain().iBlockRegistry.dump(); getMain().iItemRegistry.dump(); getMain().iItemRegistry.resetSubstitutionDelegates(); GameDataSnapshot.Entry blocks = snapshot.entries.get("fml:blocks"); GameDataSnapshot.Entry items = snapshot.entries.get("fml:items"); GameData newData = new GameData(); for (int id : blocks.blocked) { newData.block(id); } for (Map.Entry<String, String> entry : blocks.aliases.entrySet()) { newData.iBlockRegistry.addAlias(entry.getKey(), entry.getValue()); } for (Map.Entry<String, String> entry : items.aliases.entrySet()) { newData.iItemRegistry.addAlias(entry.getKey(), entry.getValue()); } for (String entry : blocks.substitutions) { newData.iBlockRegistry.activateSubstitution(entry); } for (String entry : items.substitutions) { newData.iItemRegistry.activateSubstitution(entry); } if (injectFrozenData) { for (String newBlockSubstitution : getMain().blockSubstitutions.keySet()) { if (!blocks.substitutions.contains(newBlockSubstitution)) { newData.iBlockRegistry.activateSubstitution(newBlockSubstitution); } } for (String newItemSubstitution : getMain().itemSubstitutions.keySet()) { if (!items.substitutions.contains(newItemSubstitution)) { newData.iItemRegistry.activateSubstitution(newItemSubstitution); } } } // Clear State map for it's ready for us to register below. GameData.BLOCKSTATE_TO_ID.clear(); // process blocks and items in the world, blocks in the first pass, items in the second // blocks need to be added first for proper ItemBlock handling for (int pass = 0; pass < 2; pass++) { boolean isBlock = (pass == 0); Map<String, Integer> ids = (isBlock ? blocks.ids : items.ids); for (Entry<String, Integer> entry : ids.entrySet()) { String itemName = entry.getKey(); int newId = entry.getValue(); int currId = isBlock ? getMain().iBlockRegistry.getId(itemName) : getMain().iItemRegistry.getId(itemName); if (currId == -1) { FMLLog.info("Found a missing id from the world %s", itemName); (isBlock ? missingBlocks : missingItems).put(entry.getKey(), newId); continue; // no block/item -> nothing to add } else if (currId != newId) { FMLLog.fine( "Fixed %s id mismatch %s: %d (init) -> %d (map).", isBlock ? "block" : "item", itemName, currId, newId); (isBlock ? remapBlocks : remapItems).put(itemName, new Integer[] {currId, newId}); } // register if (isBlock) { currId = newData.registerBlock(getMain().iBlockRegistry.getRaw(itemName), itemName, newId); } else { currId = newData.registerItem(getMain().iItemRegistry.getRaw(itemName), itemName, newId); } if (currId != newId) { throw new IllegalStateException( String.format( "Can't map %s %s to id %d (seen at: %d), already occupied by %s, blocked %b, ItemBlock %b", isBlock ? "block" : "item", itemName, newId, currId, isBlock ? newData.iBlockRegistry.getRaw(newId) : newData.iItemRegistry.getRaw(newId), newData.blockedIds.contains(newId), isBlock ? false : (getMain().iItemRegistry.getRaw(currId) instanceof ItemBlock))); } } } List<String> missedMappings = Loader.instance() .fireMissingMappingEvent( missingBlocks, missingItems, isLocalWorld, newData, remapBlocks, remapItems); if (!missedMappings.isEmpty()) return missedMappings; // If we got here - the load was accepted. We'll load generic repositories here. // Generic registries can fail by returning a missing mapping. missedMappings = newData.loadGenericRegistries(snapshot, getMain()); if (!missedMappings.isEmpty()) return missedMappings; if (injectFrozenData) // add blocks + items missing from the map { Map<String, Integer> newBlocks = frozen.iBlockRegistry.getEntriesNotIn(newData.iBlockRegistry); Map<String, Integer> newItems = frozen.iItemRegistry.getEntriesNotIn(newData.iItemRegistry); if (!newBlocks.isEmpty() || !newItems.isEmpty()) { FMLLog.info("Injecting new block and item data into this server instance."); for (int pass = 0; pass < 2; pass++) { boolean isBlock = pass == 0; Map<String, Integer> missing = (pass == 0) ? newBlocks : newItems; Map<String, Integer[]> remaps = (isBlock ? remapBlocks : remapItems); for (Entry<String, Integer> entry : missing.entrySet()) { String itemName = entry.getKey(); int currId = entry.getValue(); int newId; if (isBlock) { newId = newData.registerBlock(frozen.iBlockRegistry.getRaw(itemName), itemName, currId); } else { newId = newData.registerItem(frozen.iItemRegistry.getRaw(itemName), itemName, currId); } FMLLog.info( "Injected new block/item %s: %d (init) -> %d (map).", itemName, currId, newId); if (newId != currId) // a new id was assigned { remaps.put(itemName, new Integer[] {entry.getValue(), newId}); } } } } } newData.testConsistency(); getMain().set(newData); getMain().iBlockRegistry.dump(); getMain().iItemRegistry.dump(); Loader.instance().fireRemapEvent(remapBlocks, remapItems); // The id map changed, ensure we apply object holders ObjectHolderRegistry.INSTANCE.applyObjectHolders(); return ImmutableList.of(); }
public class FlipHelper { public static final FlipHelper INSTANCE = new FlipHelper(); private static final FMLControlledNamespacedRegistry<Block> BLOCK_REGISTRY = GameData.getBlockRegistry(); public boolean flip(final SchematicWorld world, final EnumFacing axis, final boolean forced) { if (world == null) { return false; } try { final ISchematic schematic = world.getSchematic(); final Schematic schematicFlipped = flip(schematic, axis, forced); world.setSchematic(schematicFlipped); for (final TileEntity tileEntity : world.getTileEntities()) { world.initializeTileEntity(tileEntity); } return true; } catch (final FlipException fe) { Reference.logger.error(fe.getMessage()); } catch (final Exception e) { Reference.logger.fatal("Something went wrong!", e); } return false; } public Schematic flip(final ISchematic schematic, final EnumFacing axis, boolean forced) throws FlipException { final Vec3i dimensionsFlipped = new Vec3i(schematic.getWidth(), schematic.getHeight(), schematic.getLength()); final Schematic schematicFlipped = new Schematic( schematic.getIcon(), dimensionsFlipped.getX(), dimensionsFlipped.getY(), dimensionsFlipped.getZ()); final MBlockPos tmp = new MBlockPos(); for (final MBlockPos pos : BlockPosHelper.getAllInBox( 0, 0, 0, schematic.getWidth() - 1, schematic.getHeight() - 1, schematic.getLength() - 1)) { final IBlockState blockState = schematic.getBlockState(pos); final IBlockState blockStateFlipped = flipBlock(blockState, axis, forced); schematicFlipped.setBlockState(flipPos(pos, axis, dimensionsFlipped, tmp), blockStateFlipped); } final List<TileEntity> tileEntities = schematic.getTileEntities(); for (final TileEntity tileEntity : tileEntities) { final BlockPos pos = tileEntity.getPos(); tileEntity.setPos(new BlockPos(flipPos(pos, axis, dimensionsFlipped, tmp))); schematicFlipped.setTileEntity(tileEntity.getPos(), tileEntity); } return schematicFlipped; } private BlockPos flipPos( final BlockPos pos, final EnumFacing axis, final Vec3i dimensions, final MBlockPos flipped) throws FlipException { switch (axis) { case DOWN: case UP: return flipped.set(pos.getX(), dimensions.getY() - 1 - pos.getY(), pos.getZ()); case NORTH: case SOUTH: return flipped.set(pos.getX(), pos.getY(), dimensions.getZ() - 1 - pos.getZ()); case WEST: case EAST: return flipped.set(dimensions.getX() - 1 - pos.getX(), pos.getY(), pos.getZ()); } throw new FlipException("'%s' is not a valid axis!", axis.getName()); } private IBlockState flipBlock(final IBlockState blockState, final EnumFacing axis, boolean forced) throws FlipException { final IProperty propertyFacing = getProperty(blockState, "facing"); if (propertyFacing instanceof PropertyDirection) { final Comparable value = blockState.getValue(propertyFacing); if (value instanceof EnumFacing) { final EnumFacing facing = getFlippedFacing(axis, (EnumFacing) value); if (propertyFacing.getAllowedValues().contains(facing)) { return blockState.withProperty(propertyFacing, facing); } } } else if (propertyFacing instanceof PropertyEnum) { if (BlockLever.EnumOrientation.class.isAssignableFrom(propertyFacing.getValueClass())) { final BlockLever.EnumOrientation orientation = (BlockLever.EnumOrientation) blockState.getValue(propertyFacing); final BlockLever.EnumOrientation orientationRotated = getFlippedLeverFacing(axis, orientation); if (propertyFacing.getAllowedValues().contains(orientationRotated)) { return blockState.withProperty(propertyFacing, orientationRotated); } } } else if (propertyFacing != null) { Reference.logger.error( "'{}': found 'facing' property with unknown type {}", BLOCK_REGISTRY.getNameForObject(blockState.getBlock()), propertyFacing.getClass().getSimpleName()); } if (!forced && propertyFacing != null) { throw new FlipException( "'%s' cannot be flipped across '%s'", BLOCK_REGISTRY.getNameForObject(blockState.getBlock()), axis); } return blockState; } private IProperty getProperty(final IBlockState blockState, final String name) { for (final IProperty prop : (Set<IProperty>) blockState.getProperties().keySet()) { if (prop.getName().equals(name)) { return prop; } } return null; } private static EnumFacing getFlippedFacing(final EnumFacing axis, final EnumFacing side) { if (axis.getAxis() == side.getAxis()) { return side.getOpposite(); } return side; } private static BlockLever.EnumOrientation getFlippedLeverFacing( final EnumFacing source, final BlockLever.EnumOrientation side) { if (source.getAxis() != side.getFacing().getAxis()) { return side; } final EnumFacing facing; if (side == BlockLever.EnumOrientation.UP_Z || side == BlockLever.EnumOrientation.DOWN_Z) { facing = EnumFacing.NORTH; } else if (side == BlockLever.EnumOrientation.UP_X || side == BlockLever.EnumOrientation.DOWN_X) { facing = EnumFacing.WEST; } else { facing = side.getFacing(); } final EnumFacing facingFlipped = getFlippedFacing(source, side.getFacing()); return BlockLever.EnumOrientation.forFacings(facingFlipped, facing); } public static class FlipException extends Exception { public FlipException(String message, Object... args) { super(String.format(message, args)); } } }
private void loadItems() { registerVariantNames(); int size = 0; ImmutableList<Item> items = ImmutableList.copyOf(GameData.getItemRegistry().typeSafeIterable()); for (Item item : items) { size += getVariantNames(item).size(); } itemBar = ProgressManager.push("ModelLoader: items", size); for (Item item : items) { // default loading for (String s : (List<String>) getVariantNames(item)) { ResourceLocation file = getItemLocation(s); ModelResourceLocation memory = getInventoryVariant(s); itemBar.step(memory.toString()); IModel model = null; try { model = getModel(file); } catch (IOException e) { // Handled by our finally block. } finally { if (model == null || model == getMissingModel()) { FMLLog.fine( "Item json isn't found for '" + memory + "', trying to load the variant from the blockstate json"); try { registerVariant(getModelBlockDefinition(memory), memory); } catch (Exception exception) { FMLLog.getLogger().warn("Unable to load definition " + memory, exception); } } else stateModels.put(memory, model); } } } ProgressManager.pop(itemBar); // replace vanilla bucket models if desired. done afterwards for performance reasons if (ForgeModContainer.replaceVanillaBucketModel) { // ensure the bucket model is loaded if (!stateModels.containsKey(ModelDynBucket.LOCATION)) { // load forges blockstate json for it ModelResourceLocation memory = getInventoryVariant("forge:dynbucket"); registerVariant(getModelBlockDefinition(memory), memory); } // empty bucket for (String s : getVariantNames(Items.bucket)) { ModelResourceLocation memory = getInventoryVariant(s); try { IModel model = getModel(new ResourceLocation("forge", "item/bucket")); // only on successful load, otherwise continue using the old model stateModels.put(memory, model); } catch (IOException e) { // use the original vanilla model } } setBucketModel(Items.water_bucket); setBucketModel(Items.lava_bucket); // milk bucket only replaced if some mod adds milk if (FluidRegistry.isFluidRegistered("milk")) { // can the milk be put into a bucket? Fluid milk = FluidRegistry.getFluid("milk"); FluidStack milkStack = new FluidStack(milk, FluidContainerRegistry.BUCKET_VOLUME); if (FluidContainerRegistry.getContainerCapacity(milkStack, new ItemStack(Items.bucket)) == FluidContainerRegistry.BUCKET_VOLUME) { setBucketModel(Items.milk_bucket); } } else { // milk bucket if no milk fluid is present for (String s : getVariantNames(Items.milk_bucket)) { ModelResourceLocation memory = getInventoryVariant(s); try { IModel model = getModel(new ResourceLocation("forge", "item/bucket_milk")); // only on successful load, otherwise continue using the old model stateModels.put(memory, model); } catch (IOException e) { // use the original vanilla model } } } } }
/** * Fire a FMLMissingMappingsEvent to let mods determine how blocks/items defined in the world * save, but missing from the runtime, are to be handled. * * @param missing Map containing missing names with their associated id, blocks need to come * before items for remapping. * @param isLocalWorld Whether this is executing for a world load (local/server) or a client. * @param gameData GameData instance where the new map's config is to be loaded into. * @return List with the mapping results. */ public List<String> fireMissingMappingEvent( LinkedHashMap<String, Integer> missingBlocks, LinkedHashMap<String, Integer> missingItems, boolean isLocalWorld, GameData gameData, Map<String, Integer[]> remapBlocks, Map<String, Integer[]> remapItems) { if (missingBlocks.isEmpty() && missingItems.isEmpty()) // nothing to do { return ImmutableList.of(); } FMLLog.fine( "There are %d mappings missing - attempting a mod remap", missingBlocks.size() + missingItems.size()); ArrayListMultimap<String, MissingMapping> missingMappings = ArrayListMultimap.create(); for (Map.Entry<String, Integer> mapping : missingBlocks.entrySet()) { MissingMapping m = new MissingMapping(GameRegistry.Type.BLOCK, mapping.getKey(), mapping.getValue()); missingMappings.put(m.name.substring(0, m.name.indexOf(':')), m); } for (Map.Entry<String, Integer> mapping : missingItems.entrySet()) { MissingMapping m = new MissingMapping(GameRegistry.Type.ITEM, mapping.getKey(), mapping.getValue()); missingMappings.put(m.name.substring(0, m.name.indexOf(':')), m); } FMLMissingMappingsEvent missingEvent = new FMLMissingMappingsEvent(missingMappings); modController.propogateStateMessage(missingEvent); if (isLocalWorld) // local world, warn about entries still being set to the default action { boolean didWarn = false; for (MissingMapping mapping : missingMappings.values()) { if (mapping.getAction() == FMLMissingMappingsEvent.Action.DEFAULT) { if (!didWarn) { FMLLog.severe( "There are unidentified mappings in this world - we are going to attempt to process anyway"); didWarn = true; } FMLLog.severe( "Unidentified %s: %s, id %d", mapping.type == Type.BLOCK ? "block" : "item", mapping.name, mapping.id); } } } else // remote world, fail on entries with the default action { List<String> missedMapping = new ArrayList<String>(); for (MissingMapping mapping : missingMappings.values()) { if (mapping.getAction() == FMLMissingMappingsEvent.Action.DEFAULT) { missedMapping.add(mapping.name); } } if (!missedMapping.isEmpty()) { return ImmutableList.copyOf(missedMapping); } } return GameData.processIdRematches( missingMappings.values(), isLocalWorld, gameData, remapBlocks, remapItems); }
public void serverStopped() { GameData.revertToFrozen(); modController.distributeStateMessage(LoaderState.SERVER_STOPPED); modController.transition(LoaderState.SERVER_STOPPED, true); modController.transition(LoaderState.AVAILABLE, true); }
public class BlockStateReplacer { private static final FMLControlledNamespacedRegistry<Block> BLOCK_REGISTRY = GameData.getBlockRegistry(); private final IBlockState defaultReplacement; private BlockStateReplacer(final IBlockState defaultReplacement) { this.defaultReplacement = defaultReplacement; } @SuppressWarnings({"rawtypes"}) public IBlockState getReplacement( final IBlockState original, final Map<IProperty, Comparable> properties) { IBlockState replacement = this.defaultReplacement; replacement = applyProperties(replacement, original.getProperties()); replacement = applyProperties(replacement, properties); return replacement; } @SuppressWarnings({"rawtypes", "unchecked"}) private IBlockState applyProperties( IBlockState blockState, final Map<IProperty, Comparable> properties) { for (final Map.Entry<IProperty, Comparable> entry : properties.entrySet()) { try { blockState = blockState.withProperty(entry.getKey(), entry.getValue()); } catch (final IllegalArgumentException ignored) { } } return blockState; } public static BlockStateReplacer forBlockState(final IBlockState replacement) { return new BlockStateReplacer(replacement); } @SuppressWarnings({"rawtypes", "unchecked"}) public static BlockStateHelper getMatcher(final BlockStateInfo blockStateInfo) { final BlockStateHelper matcher = BlockStateHelper.forBlock(blockStateInfo.block); for (final Map.Entry<IProperty, Comparable> entry : blockStateInfo.stateData.entrySet()) { matcher.where( entry.getKey(), new Predicate<Comparable>() { @Override public boolean apply(final Comparable input) { return input != null && input.equals(entry.getValue()); } }); } return matcher; } @SuppressWarnings({"rawtypes"}) public static BlockStateInfo fromString(final String input) throws LocalizedException { final int start = input.indexOf('['); final int end = input.indexOf(']'); final String blockName; final String stateData; if (start > -1 && end > -1) { blockName = input.substring(0, start); stateData = input.substring(start + 1, end); } else { blockName = input; stateData = ""; } final ResourceLocation location = new ResourceLocation(blockName); if (!BLOCK_REGISTRY.containsKey(location)) { throw new LocalizedException(Names.Messages.INVALID_BLOCK, blockName); } final Block block = BLOCK_REGISTRY.getObject(location); final Map<IProperty, Comparable> propertyData = parsePropertyData(block.getDefaultState(), stateData, true); return new BlockStateInfo(block, propertyData); } @SuppressWarnings({"rawtypes"}) public static Map<IProperty, Comparable> parsePropertyData( final IBlockState blockState, final String stateData, final boolean strict) throws LocalizedException { final HashMap<IProperty, Comparable> map = new HashMap<IProperty, Comparable>(); if (stateData == null || stateData.length() == 0) { return map; } final String[] propertyPairs = stateData.split(","); for (final String propertyPair : propertyPairs) { final String[] split = propertyPair.split("="); if (split.length != 2) { throw new LocalizedException(Names.Messages.INVALID_PROPERTY, propertyPair); } putMatchingProperty(map, blockState, split[0], split[1], strict); } return map; } @SuppressWarnings({"rawtypes", "unchecked"}) private static boolean putMatchingProperty( final Map<IProperty, Comparable> map, final IBlockState blockState, final String name, final String value, final boolean strict) throws LocalizedException { for (final IProperty property : blockState.getPropertyNames()) { if (property.getName().equalsIgnoreCase(name)) { final Collection<Comparable> allowedValues = property.getAllowedValues(); for (final Comparable allowedValue : allowedValues) { if (String.valueOf(allowedValue).equalsIgnoreCase(value)) { map.put(property, allowedValue); return true; } } } } if (strict) { throw new LocalizedException( Names.Messages.INVALID_PROPERTY_FOR_BLOCK, name + "=" + value, BLOCK_REGISTRY.getNameForObject(blockState.getBlock())); } return false; } @SuppressWarnings({"rawtypes"}) public static class BlockStateInfo { public final Block block; public final Map<IProperty, Comparable> stateData; public BlockStateInfo(final Block block, final Map<IProperty, Comparable> stateData) { this.block = block; this.stateData = stateData; } } }
static { blockIDBlacklistDefault = GameData.getBlockRegistry().getNameForObject(Blocks.bedrock) + ";"; stringOfIdsDefault = GameData.getItemRegistry().getNameForObject(Items.arrow) + ", 10; " + GameData.getItemRegistry().getNameForObject(Items.arrow) + ", 16; " + GameData.getItemRegistry().getNameForObject(Items.coal) + ", 6; " + GameData.getItemRegistry().getNameForObject(Items.diamond) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.iron_ingot) + ", 3; " + GameData.getItemRegistry().getNameForObject(Items.gold_ingot) + ", 2; " + GameData.getItemRegistry().getNameForObject(Items.mushroom_stew) + ", 2; " + GameData.getItemRegistry().getNameForObject(Items.feather) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.chainmail_helmet) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.chainmail_chestplate) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.chainmail_leggings) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.chainmail_boots) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.painting) + ", 2; " + GameData.getItemRegistry().getNameForObject(Items.painting) + ", 5; " + GameData.getItemRegistry().getNameForObject(Items.golden_apple) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.golden_apple) + ", 3; " + GameData.getItemRegistry().getNameForObject(Items.bucket) + ", 2; " + GameData.getItemRegistry().getNameForObject(Items.lava_bucket) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.milk_bucket) + ", 1; " + GameData.getItemRegistry().getNameForObject(Items.book) + ", 4; " + GameData.getItemRegistry().getNameForObject(Items.slime_ball) + ", 6; " + GameData.getItemRegistry().getNameForObject(Items.egg) + ", 4; " + GameData.getItemRegistry().getNameForObject(Items.egg) + ", 8; " + GameData.getItemRegistry().getNameForObject(Items.glowstone_dust) + ", 12; " + GameData.getItemRegistry().getNameForObject(Items.glowstone_dust) + ", 8; " + GameData.getItemRegistry().getNameForObject(Items.cooked_fish) + ", 3; " + GameData.getItemRegistry().getNameForObject(Items.dye) + ", 5, 0; " + GameData.getItemRegistry().getNameForObject(Items.cake) + ", 2; " + GameData.getItemRegistry().getNameForObject(Items.blaze_rod) + ", 2; " + GameData.getItemRegistry().getNameForObject(Items.nether_wart) + ", 6; " + GameData.getItemRegistry().getNameForObject(Items.emerald) + ", 4; " + GameData.getItemRegistry().getNameForObject(Items.emerald) + ", 6; " + GameData.getItemRegistry().getNameForObject(Items.quartz) + ", 6; " + GameData.getItemRegistry().getNameForObject(Items.map) + ", 1; " + GameData.getBlockRegistry().getNameForObject(Blocks.obsidian) + ", 4; " + GameData.getBlockRegistry().getNameForObject(Blocks.ice) + ", 3;"; }