Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
1.13/1.14 update primer

This primer is licensed under CC0, do whatever you want.

BUT do note that this is still under construction, and the contents may change anywhere from very little to drastically from now until forge 1.14 is stable, so if you derive something from this I'd prefer that you either constantly check back for updates until forge 1.14 comes out, or leave a link here so readers can see the updated information themselves.

1.13 and 1.14 are lumped together in this doc, you're on your own if you just want to go to 1.13 and not 1.14, for some reason.

Things in Advance

  • ResourceLocation now throw on non-snake-case names instead of silently lowercasing for you, so you probably should go and change all those string constants now. More precisely, domains must only contain alphanumeric lowercase, underscore (_), dash (-), or dot (.). Paths have the same restrictions, but can also contain forward slashes (/).
  • MOD LIFECYCLE EVENTS RUN IN PARALLEL. YOU NEED PROPER CONCURRENCY CONTROL IF YOU'RE COMMUNICATING TO OTHER MODS
    • In most cases, just use IMC and it should all be fine (tm)
    • Otherwise, go learn some threading or ask on discord
  • Gradle info: https://gist.github.com/mcenderdragon/6c7af2daf6f72b0cadf0c63169a87583
  • MCP renames
    • There is a script here that can take the csv's from the folder above and generated IntelliJ migration mappings, allowing you to perform MCP renames with a few clicks across your whole project.
    • The csv for 1.14 isn't up yet, so for now use this
    • Blocks.GRASS moved to Blocks.GRASS_BLOCK, with the 1-tall grass shrub taking its place. Check your codebase for bugs!
  • Registry events are now fired on mod-specific event buses. Check the bus argument to EventBusSubscriber for more info
  • slicedlime (mojang dev) has made a high-level overview of 1.14's technical changes: https://www.youtube.com/watch?v=D6P5BvItdoc

Rendering Changes

  • ModelLoader.setCustomModelResourceLocation has been removed since it is no longer needed due to the flattening.
    • Items are looked up using their own registry name, meaning foomod:fooitem will look in assets/foomod/models/item/fooitem.json by default
    • If you need something else, look into using a custom baked model in ModelBakeEvent.
  • Statemappers are now gone, replaced with a function hardcoding the old default logic in BlockModelShapes
    • This is because for vanilla usecases, the flattening has completely removed any need they have for statemappers
    • For most mods, the flattening should also solve most of the cases you need a statemapper (for appending a suffix, just do it manually; for splitting on a variant, should not happen anymore due to flattening)
  • Vanilla blockstate jsons are smarter now
    • Before: the variant string was expected in a very specific format: alphabetized list of propertyname=value pairs, based on the statemapper
    • Now: the string is split on "," and dynamically built into a Predicate<IBlockState>. This obsoletes statemapper ignoring since if you don't care about changing rendering for a given property, just don't specify it in the blockstate json
    • How overlapping predicates are handled is unknown, but from brief investigation it seems to be an error.
    • Side effect: the "normal" variant should now be named "", defining a predicate that matches all incoming IBlockStates
  • Vanilla model jsons are slightly smarter now
    • {} is now valid and represents an empty model
    • Only setting textures without setting elements is now valid, useful for e.g. setting the break particle of a TESR
  • The textures/blocks and textures/items folders have been renamed to textures/block and textures/item, matching model/. Various vanilla textures have been renamed for consistency.
    • Yes, this is automatable. Read up on sed and grep, and/or write a shell or Python script
    • Texture errors should make it obvious where the errors are (you DO keep your mods clean and you DO try not to spam the log with useless errors so you can see the real ones, right? ... right? ...)
  • In blockstate jsons, the block subdirectory is no longer inferred.
    • In other words, in a vanilla blockstate json, foo:bar no longer points to foo:models/block/bar, but rather foo:models/bar. You must put the block back in by specifying foo:block/bar in the blockstate json
    • Yes, this is also automatable, stop complaining.
    • The benefit is that you can organize models in subdirectories other than block now.
  • Custom ItemMeshDefinitions are gone as their functionality can be completely replaced with a custom baked model with custom ItemOverrideList
  • LWJGL has been bumped to version 3.x. So you can now use anything we've missed from the last 2+ years of LWJGL3 development.
    • Mojang appears to have ditched Java BufferedImage in favour of LWJGL 3's stbimage bindings. This shouldn't affect most modders.
    • Keyboard.KEY_FOO => GLFW.GLFW_KEY_FOO

Lang changes

  • Lang files are now json. instead of key=value, now one large json object with every translation inside e.g. { "block.minecraft.dirt": "Dirt" }
  • By default, blocks and item translation keys now use their registry name (replacing the colon with a dot), and the block prefix is now "block." instead of "tile.". E.g. block.minecraft.dirt, item.minecraft.diamond
    • Not as scriptable due to the flattening, but still doable
  • ".name" is also no longer added to the end of the lang

Data packs

  • Move your advancements, functions, loot tables, recipes, and structures from assets/ to data/.
  • assets/ should once again become a place where client-only resources live. Anything needed server side should be found in data/ instead.
  • It appears that Mojang has a general util method for walking a subdirectory of data/, while respecting datapack cascading/overriding, which will be great. I imagine you could move most of your configuration or machine recipes here, and gain the benefit of the cascading resource system.
    • That method is IResourceManager.getAllResourceLocations. Example usage HERE
    • IMPORTANT: If you do move some of your gameplay (e.g. machine recipes) to datapacks, be very wary of namespace collisions.
    • E.g. Mojang has already reserved data/<domain>/recipes across ALL domains for recipes participating in the vanilla recipe system, and data/<domain>/structures across ALL domains for structure NBT files. Your subfolder in the datapack probably needs to have your mod-id somewhere again. E.g. data/botania/botania/petal_apothecary/ or data/projecte/pe_custom_conversions, such that an addon or modpack can add to data/my_addon/botania/petal_apothecary/ or data/my_modpack/pe_custom_conversions
    • So if you aren't careful and put something unrelated in data/yourmod/recipes, vanilla will try to load it as a vanilla recipe JSON
  • See https://minecraft.gamepedia.com/Data_pack for more information

What's the deal with metadata?

  • Metadata has been removed. All of it. No more magic numbers!
  • Information formerly expressed using metadata is either no longer needed (blocks), flattened (blocks and items), or moved to NBT (item tool damage).
  • STOP BEING SCARED of using more block and item ID's. They are virtually unlimited now. (Well, the limit is how many Block and Item instances you can hold in memory at once. The answer is: millions of them. Blocks and Items are tiny). Of course, there are things that should still stay as variants of a single Block or Item (or as fields on a TE), but use your best judgment. Prefer flattening and using a new ID to not doing so, and just don't be stupid. Ask experienced modders on Discord or #minecraftforge if unsure.
  • Also if you are unsure, check out the vanilla wiki page on the flattening to get a feel for what should be split out into a new ID and what should stay as blockstate properties.
    • No, before you ask, you still can't make a block with 500 blockstate properties each with a dozen values. You'd run out of memory because all possible IBlockState are generated at startup. If you need something that dynamic, use a TE.
  • Using more ID's does not mean you can't reuse code, you have always been able to instantiate a class multiple times and register it under different names.

Dealing with Item metadata

  • If dealing with tool damage, move it to an NBT tag inside the "tag" tag.
    • This can be done by just using the getDamage and setDamage ItemStack calls
  • Otherwise, flatten the Item, moving each of its subvariants to a different ID.
    • Example: Instead of botania:manaresource @ <arbitrary magic number>, we now have botania:mana_diamond, botania:mana_pearl, etc.
    • If you didn't use a god item with a billion meta values for everything, good for you, you have almost nothing to do (e.g. Pam's Harvestcraft already uses a new item ID for everything instead of metas => literally zero work)
    • Split the field apart, comparing item meta values should just change to an == check on the flattened Item instances.
    • Old == checks on the unflattened item can either check tags (see below) or be an instanceof, if appropriate.
    • Update your recipes and loot tables
    • Update your lang files
  • Please don't just do NBT hacks in your Items. Unless absolutely necessary (e.g. you have infinitely many variants, in which you would have been using NBT already).
  • The cost of an extra ID is the Item instance (a handful of bytes allocated once), and the ID (a handful of bytes for the string).
  • The cost of NBT hacking is extra tags on EVERY stack (= extra storage space, extra processing overhead, extra network bandwidth consumed). Syncing a plain itemstack in our new flattened world is just sending two ints (int ID and stacksize). Adding an NBT tag significantly increases the overhead, and this overhead is paid on EVERY stack. It adds up fast.
  • In addition, many vanilla and modded subsystems will not (and should not, IMO) support NBT, most notably being the Tag system. NBT should be the exception, not the norm.
  • NO, JUST BECAUSE YOU ALREADY USED GET/SETITEMDAMAGE AND IT COMPILES DOES NOT MEAN YOU CAN LEAVE IT. FLATTEN YOUR ITEMS PROPERLY OR I WILL HUNT YOU DOWN.

Dealing with Block metadata

Here's the extremely quick rundown. Assumes prior knowledge of blockstates:

  • ALL vanilla IBlockStates are completely saved now (yes, this includes things that used to be under getActualState like fence connections, which were not saved before 1.13).
    • Things like fence connections are handled by Block.func_196242_c (updateNeighbors) and Block.func_196271_a (currently updatePostPlacement). See MCP comments for more information
    • For rendering-only properties that don't need to be set serverside, use extended states instead (an improvement to them is TBD and so this is not working just yet)
  • Remove your getMetaFromState/getStateFromMeta methods, they are no longer needed. Hopefully you aren't heavily relying on them because you were going the easy way when porting to 1.8...
  • Flatten all of your blocks, meaning that anything that might need a separate ItemBlock, needs to become a separate block itself. Inherent properties of the Block itself remain as blockstate properties.
    • Example: Vanilla logs are no longer crammed into minecraft:log[axis, variant], but are minecraft:oak_log[axis=x,y,z], minecraft:oak_bark, etc. Because a different axis log doesn't need another ItemBlock (since axis depends purely on placement position), but a different type of log needs another ItemBlock (since Items no longer have metas)
    • A simple heuristic that works in many (but not all) cases is to take any PropertyEnum VARIANT you might have had, and just pass that Enum instance into the Block's constructor and hold it as a field instead. Instead of checking the blockstate property, just check the field. See BlockShulkerBox to see how vanilla does this - it holds onto a final EnumDyeColor field for each block instance.
    • If otherwise unsure when to flatten or not, look at vanilla and emulate.
  • Flatten all of your ItemBlocks accordingly. It should just be passing the newly flattened block instances into more instances of the same class.
    • Please don't do NBT hacks, for all the reasons described above.
  • Accordingly, comparing variants should just change to == check on the flattened Block instances.
  • If you were saving blockstates using registry name + meta, you should now use NBTUtil.read/writeBlockstate. See how Endermen save their carried block for an example.

Tags (OreDictionary for ctrl+f)

  • Read https://mcforge.readthedocs.io/en/1.13.x/utilities/tags/
  • Remember: Block tags (tags/blocks/...)are only used for commands like /execute which query the blocks in world directly. Advancements and recipes both operate on ItemBlocks and use item tags (tags/items/...). Yes this will result in some duplication. If you're lazy, you can skip out on the block tags since the item tags are much more important, but doing them is still recommended for good compatibility. * For example, mods which have in-world recipes like Botania might want to use block tags. In <1.13 such mods must slowly iterate the OreDictionary (which is built for items, not blocks) and/or perform caching logic. With block tags, it would just be a constant time set lookup.

Recipes

  • You need a json for every recipe now (dramatic music plays)
    • But not really: You just need a json to allow it to be disabled by datapacks (and syncing to client)
    • Basically there is a registry from type -> Json deserializer, so your recipe jsons can now have whatever custom JSON format you want, including all code (think Loot table LootFunctions and LootConditions).
    • See vanilla mapcloning and mapextending.json and their in-code equivalents, the json simply specifies the type, and the entire recipe is implemented in code.
    • For ordinary recipes, you probably should convert them to jsons.
  • TBD: Mojang seems to have some kind of auto recipe dumper at net.minecraft.data.RecipeProvider that generates the recipe json as well as an advancement to unlock the recipe. This tool appears to be runnable by running the minecraft jar with a different start class.
  • Furnace recipes are now be specified using the normal recipe JSONs.

Advanced Recipes

  • You can now register custom deserializers for recipes, which are dispatched based on the type field in the recipe json.
  • Your recipe type must be syncable over the network (since recipes are now sent to all clients on login and datapack reloads)
    • No, don't just send the json text over. These are sent on login, so you don't want the client to waste time reparsing stuff. Ideally, you want to send the absolute least amount of information you can to define the recipe.
  • One-to-many and super dynamic recipes are still TBD, talk with forge devs or modders of interest (tterrag) if you want to discuss a solution for this

Commands

  • Commands have been overhauled, and now use a separate Mojang library called Brigadier (it's not obfuscated, so you can just look at the source)
  • Command syntax is now much more declarative (instead of trying to manually parse things out of the command string each time)
  • Command syntax now synced from server to client
  • Tab completion only asks the server if the specific argument in the command says that it should
  • Completion for things that have a static fixed set of options done clientside (e.g. /gamemode)
  • Not much is known yet, see vanilla for examples

Fluids and waterlogged blocks

  • 1.13 brings a new "water in block" mechanic
  • The interfaces are very general - World now has getFluidState and setFluidState methods, and fluids are elevated to almost block-level status (they can even have their own IProperty's)
  • However, the current fluid state implementations usually just defers to blockstate properties on the underlying block such as the waterlogged property.
    • The system is likely incomplete; expect this to evolve in future versions to be like Bedrock Ed (where water can reside in any block)
  • more info on classes to implement, etc. when everything's deciphered
  • Fluids are now a registry object in vanilla, and your == Blocks.WATER/LAVA checks probably need to be changed to tag checks (see BlockCoral.canLive for an example)

World gen changes

Data Fixers

  • Got an extremely category-/type-theory heavy makeover due to the extreme changes to the world format
  • No really, here's the paper: https://arxiv.org/ftp/arxiv/papers/1703/1703.10857.pdf
  • TBD as it gets deciphered, but I imagine fixers will not be very useful for mods anymore.

Containers

GUI/Mouse/Keyboard/Input/Keybindings

  • LWJGL3 now uses GLFW as the backing windowing system, so things have shifted accordingly.
  • If you need something, look around to see if MouseHelper and KeyboardListener have what you need already (both accessible from Minecraft). Common things like the mouse position and button states etc are already here.
  • Otherwise, you can use direct GLFW calls to get input state, see glfw input guide. The article is for C, but you can generally directly translate by adding the GLFW class in front of the function names and constants given. E.g. glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS => int state = GLFW.glfwGetKey(mc.mainWindow.getHandle(), GLFW.GLFW_KEY_E) == GLFW.GLFW_PRESS
  • Notably, Gui method signatures have changed a bit. See IGuiEventListener
    • mouseClicked and mouseReleased receives the x, y, and modifiers
    • mouseDragged receives the same, plus the x and y drag amounts
    • mouseScrolled receives the amount scrolled
    • keyPressed and keyReleased receives the keyCode, scanCode, and modifiers. The scan code is likely not useful to you, check the keyCode with constants in GLFW instead, e.g. keyCode == GLFW.GLFW_KEY_E
    • charTyped receives a any textual input, as the form of unicode codepoint and the modifiers. Note that java char is only 16 bit so cannot encode all possible unicode points, but should be "enough" for most keyboard input uses. This call should be used for text input purposes, while keyPressed should be used for "key bind" purposes.
  • To check whether a key binding is pressed, given the keyCode and scanCode, call <KEYBINDING_OBEJCT>.isActiveAndMatches(InputMappings.getInputByCode(keyCode, scanCode))
  • Misc
    • mc.setIngameFocus -> mc.mainWindow.grabMouse/ungrabMouse

Misc Things

  • Vanilla now has a "different AABB depending on where you look" system (aka vanilla diet hoppers but even better). Play with the hopper in 1.13 to see what I mean. See hopper or end portal frame block classes for examples.
  • Structure Blocks (and anything you made using them) need to be reloaded into a 1.12 world, the world run in 1.13, then resaved in 1.13. No idea why Mojang doesn't have an automated way to fix this, but it is what it is
  • Block attributes like their material or hardness are now passed in a builder/POJO to the block constructor, and are final
    • Similar for Items
  • Blocks no longer have a creativetab, that belongs on their ItemBlocks
  • Biome ids are internally ints now instead of bytes, which raises the maximum number of allowed biomes from 255 to 2 billion.
  • Enchantments are now stored by registry name instead of int id (about time...)
  • A word about integer ID's
    • For Items and Blocks, you should have already switched to fully using registry names for everything. The registry name <-> int ID maps still exist in vanilla for performance purposes, but they should never be used for anything other than network communication because they are NOT guaranteed to be the same after joining a different world. This should already be an established modding convention since 1.8, but people still break it, so I'll mention it again :P
  • There's lots of superinterfaces on world now representing different things you can do (e.g. there's an interface for read-only access to the world). If possible, try using the least specific one.
  • Most nameable things that still used strings now use text components, so translate all the things!
  • There's multiple kinds of air block now (air, void_air, and cave_air). So if you're doing == Blocks.AIR checks still, change them to IBlockState.isAir checks
  • More things are stored in registries now: Entities, BiomeProviders, ChunkGenerators, ParticleTypes, Stats, Paintings
  • As always, check the vanilla 1.13.x patch notes for anything I missed that's gameplay-facing
  • Your world renderers (RenderWorldLastEvent) look weird? give this a read: https://discordapp.com/channels/313125603924639766/454376090362970122/588257071812837376

Nitty Gritty Random Things (Ctrl+F section)

  • SideOnly(Side.CLIENT) => OnlyIn(Dist.CLIENT)
  • SidedProxy => DistExecutor
    • e.g. public static IProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new);
    • Why the additional lambda at the front? It's to prevent the ClientProxy and ServerProxy classes from directly being referenced by the main mod class.
  • mcmod.info moved to mods.toml, see MDK examplemod src/main/resources/META-INF/mods.toml
  • EventBus is a separate library (fix imports). Can register handlers without annotations (so you can use private methods for example). See MDK ExampleMod
  • Loader.isModLoaded => ModList.get().isLoaded()
  • important renames
    • Entity.onUpdate => tick
    • Entity.onEntityUpdate => basetick
    • Entity.setDead => remove
    • World.setBlockToAir => removeBlock
    • World.scheduleUpdate => world.getPendingBlockTicks().scheduleTick (blocks and fluids have separate scheduled ticks now)
    • Block methods: IBlockState moved to front of all forge methods
  • checking physical side => FMLEnvironment.dist
  • checking logical sides:
    • getEffectiveSide => EffectiveSide.get (HIGHLY encouraged to move to world.isRemote checks)
    • getting logical server: ServerLifecycleHooks.getCurrentServer()
  • network: SimpleImpl -> SimpleChannel
  • ScaledResolution.<x> => Minecraft.getInstance().mainWindow.<x>
  • isOpaqueCube => remove, mc now checks this with the block's voxelshape
  • ArmorMaterial => implement IArmorMaterial, no more enum hackery needed
  • ToolMaterial => implement IItemTier, no more enum hackery needed
  • EnumHelper => gone. some enums were abstracted to interfaces by vanilla for us (like the above), and the rest have moved to dedicated create methods on each individual enum. For example, BannerPattern.create(...)
  • TileEntity.shouldRefresh => logic moved to Block.onReplaced. see BlockFurnace.onReplaced for an example.
  • getBlockFaceShape => gone, the game is smart enough to check your VoxelShapes from getShape now

Cross-referencing, a quick how-to

  • Oh no! Method FooClass.BarMethod disappeared in 1.13/1.14! Where did it go? Follow these easy steps for a guaranteed 80% success rate!
  1. Open a 1.12 workspace (this is why you use a separate workspace to update, by the way)
  2. Browse to FooClass.BarMethod
  3. Use your IDE's find usages tool to see where it was called from in vanilla
  4. Pick a call site
  5. Go to that same call site in 1.13/1.14
  6. What does it call instead?
  7. ???
  8. Profit

(if these steps don't apply, then you're allowed to ask)

Some parting words

  • Ask experienced modders for help on Discord/IRC or look at their own ports
  • Help others needing help, but only if you're 100% certain what you're talking about. As always, vanilla should be a first reference regarding mechanisms and conventions

Reporting Errata

  • If you notice something incorrect in this primer, please let me (williewillus) know as soon as possible on the Modded Minecraft discord, twitter, or #minecraftforge IRC if I'm there. I don't want to spread misinformation, so I appreciate the speedy notification.
@Boundarybreaker

This comment has been minimized.

Copy link

commented Jul 15, 2018

Are you planning to update the primer for the new information about 1.13?

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Jul 15, 2018

Are there any things you're specifically aware of that aren't listed here?

@CJMinecraft01

This comment has been minimized.

Copy link

commented Jul 16, 2018

One thing you showed but didn't explicitly state regarding the language file. Prior to 1.13 the name would be something like tile.dirt.name and 1.13 onwards is now block.minecraft.dirt, appending the domain name to the language key. I'm not sure what the impact is on unlocalized names but I assume that these unlocalized names have been replaced by their registry names and hence the language file now uses the domain name in the default item and block language key

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Jul 17, 2018

yup, noted here:
By default, blocks and item unlocalized names now use their registry name (replacing the colon with a dot)

@Drullkus

This comment has been minimized.

Copy link

commented Jul 19, 2018

Regarding

  • E.g. Mojang has already reserved data/<domain>/recipes across ALL domains for vanilla crafting recipes, and data/<domain>/structures across ALL domains for structure files. Your subfolder in the datapack probably needs to have your mod-id somewhere again. E.g. data/botania/botania/petal_apothecary/, such that an addon can add their recipes to data/my_addon/botania/petal_apothecary/

So there's no way to coerce Vanilla to add a new deserializer for new recipe types? Or is because their system for parsing stuff in this folder a hardcoded mess? Or both?

Also:

  • If you are smart and methodical about how you do it, this port should be extremely straightforward. There will be tedious parts but at every step it should be crystal clear what needs to be done.
    • Unless you're doing worldgen in which case good luck and godspeed lol

[internal screaming]

@lofcz

This comment has been minimized.

Copy link

commented Jul 19, 2018

When is 1.13 branch coming up for Forge on github?
Thanks in advance.

@hYdos

This comment has been minimized.

Copy link

commented Jul 21, 2018

if ANYONE has the 1.13 server src plz PLZ send it 2 me

@xfl03

This comment has been minimized.

Copy link

commented Jul 23, 2018

@hYdos
What's your email?

@pizza2004

This comment has been minimized.

Copy link

commented Aug 18, 2018

@Drullkus I imagine it's specifically so that mod data packs don't cause issues if loaded into a vanilla world.

@dargonforce

This comment has been minimized.

Copy link

commented Sep 25, 2018

instructions unclear, I accidentally pirated terraria

@ARandomGuy213

This comment has been minimized.

Copy link

commented Oct 14, 2018

Nice work. This is really helpful! How did you find this info?

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Nov 3, 2018

@GamerzForLif
access to the decompiled code, snapshot changelogs

@stfwi

This comment has been minimized.

Copy link

commented Dec 10, 2018

Hey willie, thanks for fiddling that out for all, much appreciated (+1).

@CatRabbit499

This comment has been minimized.

Copy link

commented Feb 10, 2019

Does anyone know what the replacement for this enum is?:
NetworkRegistry.INSTANCE.registerGuiHandler(Modid.INSTANCE, Modid.GUI_HANDLER = new GUIHandler())

The register method for a GUI handler isn't where it was in 1.12.2.

Example from my simple 1.12.2 mod:
NetworkRegistry.INSTANCE.registerGuiHandler(TestModPleaseIgnore.INSTANCE, TestModPleaseIgnore.GUI_HANDLER = new GUIHandler());

(I'm currently porting it to the 1.13-pre test build 1.13-24.0.172-1.13-pre)

@LordMonoxide

This comment has been minimized.

Copy link

commented Feb 12, 2019

Hey, it seems that the information about datapacks might be incorrect. IResourceManager.getAllResourceLocations is only giving me locations from my assets directory. See my post for more info.

If anyone has information on accessing files in datapacks, it would be greatly appreciated.

@liach

This comment has been minimized.

Copy link

commented Feb 16, 2019

@LordMonoxide It will give you the correct locations for data stuff when and only when you start a dedicated or integrated server. In other words, that is when you load a local world in a client or run a server.

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Feb 16, 2019

@LordMonoxide yes, datapacks are only on the logical server.

@galaran

This comment has been minimized.

Copy link

commented Feb 17, 2019

LWJGL section addition: LWJGL 3.x switched input library from JInput to GLFW, which has different key mapping. See GLFW_KEY_* constants in org.lwjgl.glfw.GLFW

@Dalarion

This comment has been minimized.

Copy link

commented Feb 21, 2019

How do I add ArmorMaterial now ? Cause I can't use EnumHelper.addArmorMaterial(); ?

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Feb 24, 2019

@Dalarion updated

@peter1745

This comment has been minimized.

Copy link

commented Mar 1, 2019

I can't figure out how to register TileEntities, I've found that I need to register a TileEntityType, but then the game crashes on load

@peter1745

This comment has been minimized.

Copy link

commented Mar 1, 2019

I can't figure out how to register TileEntities, I've found that I need to register a TileEntityType, but then the game crashes on load

Nevermind, i figured it out, you have to register the TileEntityType very early on in mod construction, in your mod classes constructor

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Mar 5, 2019

@peter1745 no, that's not the right time. TileEntityType should be registered in a registry event.

@derfl007

This comment has been minimized.

Copy link

commented Mar 13, 2019

Changing id:model to id:block/model in the blockstates doesn't work for me, i still have to leave out the block, otherwise it references to models/block/block/model.json
Edit: Okay so this only happens for some blockstate files, could it be that it only happens to non-forge blockstate files?

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Mar 14, 2019

@derfl007 the change noted is only for the vanilla blockstate json format. the forge format needs to be updated, but currently uses the old way

@marcus8448

This comment has been minimized.

Copy link

commented Mar 15, 2019

Is there any way to make an EnumRarity? There's no create method

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Mar 15, 2019

@marcus8448 you'll have to ask forge to add one

@Parker8283

This comment has been minimized.

Copy link

commented Mar 23, 2019

@CatRabbit499
You want to register your GUI handler with ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.GUIFACTORY, ...);, where the ... parameter is replaced with a Supplier to a Function that takes an FMLPlayMessages.OpenContainer as its parameter and returns a GuiScreen. See this for how IronChest does it.

To open a GUI, you would use the NetworkHooks.openGui family of functions. Here's how IronChest does it.

I'm not sure if this would count as a good thing to add to the Primer since it's more of an FML update than a Minecraft update, but that's what you're going for.

@Ivorforce

This comment has been minimized.

Copy link

commented Mar 26, 2019

For anybody intending to read states from legacy block ID + metadata:

public static IBlockState fromLegacyMetadata(String blockID, byte metadata)
{
    int legacyBlockID = BlockStateFlatternEntities.getBlockId(blockID);
    Dynamic<?> dynamicNBT = BlockStateFlatteningMap.getFixedNBTForID((legacyBlockID << 4) + metadata & 15);
    NBTTagCompound compound = (NBTTagCompound) dynamicNBT.getValue();
    return NBTUtil.readBlockState(compound);
}

I haven't tested it yet but it should work roughly like this for any vanilla entries. I'm not sure how Forge is intending to solve this for modded stuff yet though.

@cpw

This comment has been minimized.

Copy link

commented Mar 30, 2019

SidedProxy

=> DistExecutor

e.g. public static IProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new);

Please note : ()->()->new ClientProxy() is the preferred form - I believe the method reference will cause the method and class to resolve in the context of the primary class, not the lambda, and could therefore fail on the wrong side.

@Wabbit0101

This comment has been minimized.

Copy link

commented Apr 11, 2019

Soooo...where did all the @Optional.InterfaceList and @Optional.Interface annotations go? Is this no longer a thing and if not, how do we optionally include APIs and have them magically go away (OptionalMod doesn't seem to be a replacement but that's the closed thing I've been able to find...) Are mod authors expected to provide their own annotations for instance...ala JEI and InvTweaks?

@RobertSkalko

This comment has been minimized.

Copy link

commented Apr 24, 2019

how do you get stuff like EnumParticleTypes now?
Edit: it's just Particles now.

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Apr 30, 2019

@Wabbit0101 capabilities and IMC.

@multiplemonomials

This comment has been minimized.

Copy link

commented May 6, 2019

The textures/blocks and textures/items folders have been renamed to textures/block and textures/item

[external screaming]

I have already spent too many hours of my life fiddling around with incorrect JSON block/texture/whatever paths. I miss the days when you could just write regular code...

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented May 10, 2019

@multiplemonomials you do realize a one-line sed script could fix this completely for you? you're a programmer, you should aim to automate all of this away.

besides, you don't even have to change this for your own mod if you don't want to, it's only mojang's textures that have moved.

don't complain about trivial things :P

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented May 20, 2019

fixed

@lehjr

This comment has been minimized.

Copy link

commented May 24, 2019

Probably a good time to update the info here to reflect extended states being replaced with... um... welll, this: MinecraftForge/MinecraftForge#5564

@desht

This comment has been minimized.

Copy link

commented Jun 9, 2019

So, a few major things I've hit so far in porting from 1.13.2 to 1.14.2:

  • Containers & GUI creation has changed
    • ExtensionPoint.GUIFACTORY is gone. Container types are registry objects now and are associated with a GUI object (subclass of Screen) via ScreenManager.registerFactory()
    • IInteractionObject is gone, replaced with INamedContainerProvider
    • So IInteractionObject#getGuiID() is also gone, maybe replaced with an integer parameter in IContainerProvider#createMenu() ? FMLPlayMessages.OpenContainer now also has an int rather than ResourceLocation id field which backs that up. Update: the integer windowId is just an internal value you pass to the super constructor, but never need to otherwise worry about.
    • Container constructor now takes a ContainerType parameter which is a registry object, as mentioned above.
    • Haven't really figured this out yet. See https://www.minecraftforge.net/forum/topic/71577-1142-containers-and-guis/ for some more info
  • BlockFaceShape has gone, not needed anymore. "the game is smart enough to check your VoxelShapes from getShape now"
  • There's a new BlockRayTraceResult class which is used in several place to aggregate some parameters. E.g. ItemUseContext and BlockUseContext constructors, ItemStack.onItemUseFirst() etc.
  • RecipeSerializers is gone; recipe serializers are now registry objects and should be registered as in https://github.com/desht/ModularRouters/blob/MC1.14-master/src/main/java/me/desht/modularrouters/core/ModRecipes.java#L23-L24 and used as in https://github.com/desht/ModularRouters/tree/MC1.14-master/src/main/java/me/desht/modularrouters/recipe
@multiplemonomials

This comment has been minimized.

Copy link

commented Jun 10, 2019

Okay, got a good start on my 1.13 port. A few questions:

  • What's the replacement for FMLCommonHandler.instance().getMinecraftServerInstance()?
  • I18n is now marked as client-only. Is there any possible way to do translations on the server side now? Asking... for a friend
  • What's the equivalent for the acceptableRemoteVersions = "*" argument for @mod? I want to make it so my mod is only required on the server.
@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Jun 11, 2019

@multiplemonomials

  1. that's in the doc
  2. Never translate on the server, send TextComponentTranslations to the client
  3. dunno
@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Jun 11, 2019

@desht updated for containers

@multiplemonomials

This comment has been minimized.

Copy link

commented Jun 11, 2019

I could not find anything about FMLCommonHandler anywhere in this doc, or anywhere else...

I ended up replacing my

FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().sendMessage(messageText);

with

MinecraftServer server = deadEntity.world.getServer();
server.getPlayerList().sendMessage(new TextComponentString(messageText));
@Rongmario

This comment has been minimized.

Copy link

commented Jun 11, 2019

@multiplemonomials check again in the Nitty Gritty Random Things section.

@Wabbit0101

This comment has been minimized.

Copy link

commented Jun 11, 2019

PotionHelper -> PotionBrewing EXCEPT all of the mod-used APIs like addMix, addContainer seem to be private now with no apparent replacements. As these don't seem to be noted above:

  • PotionTypes -> Potions
  • PotionType -> Potion
  • Potion -> Effect
  • PotionEffect -> EffectInstance
@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Jun 12, 2019

@Wabbit0101 the forge AT should be making those public, if not the names probably changed and the AT hasn't been updated. ask around on discord and file a bug

@desht

This comment has been minimized.

Copy link

commented Jun 13, 2019

Couple of notes regarding (ticking) mod tile entities:

  • Be sure that your TE implements ITickableTileEntity and not ITickable. If you don't, you won't see any errors, but your TE won't tick.
  • When registering your TE, be sure to pass all the blocks for that TE (most likely just one block, but can be multiple) to the TileEntityType.Builder.create() method. Again, if you don't - no errors, but no ticking (and no rendering, if you're using a TESR). Probably good practice to do this for every TE regardless.
@Justsnoopy30

This comment has been minimized.

Copy link

commented Jun 16, 2019

@williewillus About the MCP section, how do you update plain non-forge MCP 1.12.2 to 1.14.2?

@williewillus

This comment has been minimized.

Copy link
Owner Author

commented Jun 16, 2019

@Justsnoopy30 this doc doesn't support non forge cases, I assume if you're using mcp without forge you know what you're doing :D

@Wabbit0101

This comment has been minimized.

Copy link

commented Jun 17, 2019

@multiplemonomials I'm stumped here as well...but I think you use ServerLifecycleHooks.getCurrentServer() to get the server...FakePlayer does! (Warning I'm still in the omg-bellions-and-bellions-of-compile-errors phase so i cannot verify...)

@desht

This comment has been minimized.

Copy link

commented Jun 18, 2019

@williewillus - one note to update: "For rendering-only properties that don't need to be set serverside, use extended states instead (an improvement to them is TBD and so this is not working just yet)"

The IModelData interface is now in Forge, and works - MinecraftForge/MinecraftForge#5564. At least, I had it working well in my mod for 1.13.2, but Forge for 1.14.2 currently doesn't fire the ModelBakeEvent which prevents my mod from being able to test it out there (MinecraftForge/MinecraftForge#5805). Update it's fired since Forge 26.0.37 and appears to be working fine.

@Sinhika

This comment has been minimized.

Copy link

commented Jun 18, 2019

A note for people porting their armor and tool mods from 1.12.2 or lower: for models the material name needs to be prefixed by the modid, (e.g. "simpleores:copper" instead of just "copper") otherwise the texture loading routine defaults to searching in the "minecraft" resource location and fails to find your armor textures (e.g. there is no "minecraft:textures/models/armor/copper_boots"). I haven't ported the tools over yet, but I anticipate finding the same quirk.

Also, it pays to read the fine print in the documentation. In recipes, an "item" and a "tag" are NOT the same thing, and if you specify your ore dictionary tags as "item", your recipe will give up in despair when it tries to load a non-existent "forge:ingots/copper" ITEM. It works fine if you tell it to use a "tag" : "forge:ingots/copper" TAG. (Presuming you defined ingots/copper in the first place).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.