Leaderboard
Popular Content
Showing content with the highest reputation on 06/21/17 in all areas
-
Minecraft 1.12: The newest version of Minecraft has been released. Forge has been updated to support this new version. However due to the way Mojang implemented the Recipe changes there are a lot of under the hood changes that we need to do. Most notably re-writing on of the largest/most intricate systems of Forge, The Registry system. This will take some time, so do not expect a recommended release quickly. However if you are a modder you can start using the current versions to build against. Some API's may change in the early days of Forge so be sure to be ready for that. I'm sorry, I usually try my best to maintain binary compatibility, but it's just what will need to happen. For users, you can use the current builds. But just be warned that things are actively being developed and we ask to please responsibly report issues on the forum. Once I finish the rewrite and get a stable recommended build of Forge out I will make a more detailed post listing all the major changes like I always do. New Policy on Coremods: Sadly core modding is still a thing. As always we request that you guys attempt to work with us to get changes into Forge instead of core modding it yourself. However, if you MUST we have decided to put forth to the community a few 'Best Practices' for core modding. The intention is that large communities such as FTB, Technic, and Curse work with us to promote these best practices. 1) Coremod must be the coremod only, and no extra library/features/apis/etc. There are far too many coremods in the community that package tons of classes that have nothing to do with the modifications they make to the game together so that people will be forced to use their coremod just because they want a utility. This is bad. So Coremods themselves should be limited to JUST the IFMLLoadingPlugin, and IClassTransformers, and as few utility methods needed to make those hooks run. 2) Coremod binaries must be signed. This is a very basic thing that just verifies the person/organization we think made the coremods actually did. It also verifies that the file that was downloaded has not been modified in any way. As it sits there will NOT be any central authority on the keys used to sign things. So Self-signing will be allowed as long as you provide the community your signature. Starting in 1.13, with the loading system rewrite, users will be prompted to accept signatures of coremods. It is our intention to work with people like FTB, Curse, and others to make these signatures easy to use and manage. For example a user would say they trust FTB, and wouldn't be prompted for every coremod that exists in a FTB modpack. For the technical side you can read more about Jar Signing here: https://docs.oracle.com/javase/tutorial/deployment/jar/signindex.html 3) Coremods should be visible source. This will be a controversial standard, but my thoughts on it is that if you're screwing with someone else's code (which is the only reason to ever write a coremod), then you should be willing to show what you are doing. It is stressed that this is VISIBLE SOURCE only. It is not a requirement that you allow others to use your code, or modify and distribute it. It's simply that we can see it. The signatures and visible source are NOT designed to be security measures. As there is nothing preventing malicious code from being signed and a user accepting it. This is just the risk you run with Minecraft modding as you're running compiled code from random people on the internet. This is however designed to make the community more open and try and stem the number of coremods out there that have no reason to be coremods. Major Policy change: I am happy to officially announce a new member of the Forge team. Everyone welcome Mezz. His official responsibilities are to be the Pull Request, and Issues manager. Basically, he's the guy you yell at if your PR/Issue is rotting on github. He's the guy who is tasked with reminding me that they exists. He will be the one responsible for filtering all the PRs/Issues before they get to me. So I don't have to deal with telling you guys to follow the standards like making a test mod, posting logs, etc.. In addition, he is also the one who decides if old versions will have PRs accepted. Yes this means there will be a limited development system for older versions. How far back that means is ENTIRELY up to Mezz. However the rules are that ANY pr adding features for a old version MUST be applied and accepted for the current version FIRST. Save for features that would have no place in the new version. Example being adding a new achievements hook when the new version removed achievements. It will still be our official stance on this forum to only provide support for the Current version, and the previous version. However, if the community wishes to have a few dedicated people step forward and become our Legacy support team them I am willing to work with them and see what we can set up. The main reason we do not provide support for old versions is simply we do not have the manpower. So start helping out! Response From Sponge:3 points
-
If you ever built your mod with the build Gradle task, you may have a source JAR in the build/libs directory of your mod's workspace. This will contain your source code obfuscated to SRG names. BON2 can deobfuscate a compiled JAR from SRG (obfuscated) to MCP (deobfuscated) names, but probably not a source JAR. You can then decompile it with a decompiler like Bytecode Viewer. The decompilation process isn't perfect and all comments are stripped during compilation, so the code you get out of it won't be exactly the same as the original code. If you use version control software like Git and host a copy of your repository on a site like GitHub, you can retrieve any version of your code. This will make it much less likely that you'll lose anything.1 point
-
Forge already provides those classes for you. ShapedRecipes, ShapelessRecipes, ShapedOreRecipe and ShapelessOreRecipe exist in the version of forge I've mentioned. You should however use the json recipe system as that is the suggested way of doing recipes now (since it makes it easier for the end-user to edit recipes on demand which is common nowdays and Mojang may introduce S->C json recipe sync in the future versions).1 point
-
metadata can only go up to 16(actual values [0 - 15]). Apart from that the power your block sends is defined in Block::getWeakPower method, you can access your tile from it, access the capability and get the power you are emitting. You might need to notify neightbour blocks when you are changing that value with World::notifyNeighborsOfStateChange (see how BlockLever does that). You can do that directly from your tileentity.1 point
-
You're using the wrong Register class (Tcp.Register), while you should be using RegistryEvent.Register. Also, because the RegistryEvents are called before preInit, you should annotate the class with @EventBusSubscriber, so the class actually gets registered.1 point
-
Changing vanilla textures (or models) is the same process as making a resource pack, like Draco said. To change the generation of ores, you can subscribe to OreGenEvent.GenerateMinable, check the EventType and set the result to DENY to cancel it. Then make your own IWorldGenerator and generate the ores as you want them.1 point
-
You mean replace the textures? Yeah, just put them into your assets directory so that their path is the same as the vanilla texture.1 point
-
The unlisted properties aren't used in equals, so they won't be taken into account when using extended block states as keys for a cache. To get around this, make the keys of type Pair<ImmutableMap<IProperty<?>,Comparable<?>>, ImmutableMap<IUnlistedProperty<?>,Optional<?>>> which is the ugly parametrised type that represents Pair.of(state.getProperties, state.getUnlistedProperties()) This forces the unlisted properties to be taken into account when checking whether the state is already present in the cache. I use this approach in a model here if you want to see an example.1 point
-
Registry events are fired before preInit, so you need to annotate the event handler class with @Mod.EventBusSubscriber to automatically register it at mod construction time (or register it manually). In addition to this, you're registering an instance of the event handler but your methods are static; which is incorrect. Static event handler methods require you to register the Class object rather than an instance, as explained in the documentation. You need to set the registry name of an IForgeRegistryEntry like Block or Item before you register it. Having a constructor modify static fields in a class where there there are no instance fields or methods and calling this constructor purely for the side-effects is very strange and probably a bad idea. If you need to do more stuff to the Items in preInit, create a regular static method instead of a constructor. ModelLoader is a client-only class and can't be referenced from common code. ModelRegistryEvent should be handled in a client-only class that's only registered with the event bus on the physical client (pass Side.CLIENT to the @Mod.EventBusSubscriber annotation or manually register it in a method only called on the physical client).1 point
-
It's not absolutely required, but it's a good idea to avoid potential conflicts. All unlocalised names are used as keys in the same Map, so your unlocalised name's translation could overwrite or be overwritten by the same name from another mod. I recommend using the Item's registry name (IForgeRegistryEntry#getRegistryName) as the unlocalised name as it already includes the mod ID.1 point
-
That's because this class is never ever even "seen" by Minecraft. (You HAVE to call setRegistryName(string) in your block. Either directly in the constructor or later down the road when you register it. (setRegistryName returns the block itself, with the registryName set)) Create a new class, which you will be using for registration of blocks (and items (held blocks & blocks stored in inventories etc are item (technically ItemBlocks))) Annotate this class with @EventBusSubscriber Create a public static void method, and subscribe it to the Register<Block> event. Now, I like to put all my blocks in a list/set collection, and for that collection, call forEach(event.getRegistry::register). Of course, you can always just use a for-each loop and call event.getRegistry().register(block). If you do not want to use a collection, use event.getRegistry().registerAll(), and supply the registerAll all your blocks. (block1, block2... blockn) Now, create another public static void method, but subscribe to the Register<Item> event instead. For each block you registered in just now, you will need to create a corresponding ItemBlock (so that it can exist in inventories & your hand etc) Either for-each loop over the collection, create a new ItemBlock(block) & set it's RegistryName to the block's RegistryName and register it in the event, OR use another lambda expression: blockCollection.stream().map(block -> new ItemBlock(block).setRegistryName(block.getRegistryName())).collect(Collectors.toList()).forEach(event.getRegistry()::register); Wee bit messier than before. (for each block in this collection(that contains blocks!), create a new ItemBlock, and set it's RegistryName to the block's RegistryName. Put this new ItemBlock into a new list, and for each thing in this new list, register). if you have any normal items, you can simply do the same thing we did with blocks, and call forEach(event.getRegistry::register) on the item-list. (or as said stick to a simple for-each loop)1 point
-
Chiming in as one of the other leaders of Sponge, I've always believed that making heavy modifications to the game (as coremods sometimes do) would benefit from being viewed source, since often times debugging odd interactions between SpongeForge (and SpongeCommon as the larger part) have been often times difficult to say the least to work out where the issue lies. That being said, I strongly support the idea around coremods being viewed source for the sake of inter-coremod compatibility overall, as the goal with SpongeForge has always been about remaining compatible with as many mods as possible out of the box (even if the technological attempts at maintaining that compatibility is not as evident or thought up very fast). As @Zidane has mentioned, SpongeForge will be making the necessary changes in the very near future to abide by these requirements. As per usual, my goal with inter-mod compatibility is always to provide as much descriptive console spam error logs to help Sponge and/or the mod itself get a better fix and make the users happier overall.1 point
-
1 point
-
Stairs are easier than slabs. For complete source listing look at https://github.com/localtoast9001/forge-mods/tree/1.8. How stairs work in the game Each stair is a block derived from net.minecraft.block.BlockStairs. The base class controls collision, placement, and block state properties. The stairs block references its full cube block object for material properties. The stairs block has a lot of different variants through its block state to describe the stair's orientation. Since each variant potentially has its own model, you'll need to test all combinations. Design Considerations I originally wanted to do stairs for stained bricks. The cube block for stained bricks is one block with 16 variants for each color. In 1.7, the stairs block uses all the metadata for orientation, so I needed 16 different types of stairs. I continued this pattern in 1.8, even though BlockStairs now takes a full IBlockState in its constructor. I didn't experiment. Classes you will need A stairs block class derived from net.minecraft.block.BlockStairs - This is used for block registration and to initialize the base class with properties from the cube block. To get a block state object from the cube block, you can call block.getStateFromMeta(int metadata). metadata is 0 if your cube block has no variants. Example: /** * Stained brick stairs. * */ public class BlockStainedBrickStairs extends BlockStairs { /** * Initializes a new instance of the BlockStainedBrickStairs class. * @param block the stained bricks block. */ public BlockStainedBrickStairs( final BlockStainedBricks block) { super(block.getStateFromMeta(0)); Block Registration Stairs reuse the common ItemBlock class, so stairs are registered like any other normal block in your Mod's init event handler. Example: BlockStainedBrickStairs stairs = new BlockStainedBrickStairs( stainedBrickBlocks); GameRegistry.registerBlock(stairs, stairs.getId()); Models You need one blockstate file and 3 model files (normal, inner, and outer) for your stairs. Example/template blockstate file: { "variants": { "facing=east,half=bottom,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs" }, "facing=west,half=bottom,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs", "y": 180, "uvlock": true }, "facing=south,half=bottom,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs", "y": 90, "uvlock": true }, "facing=north,half=bottom,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs", "y": 270, "uvlock": true }, "facing=east,half=bottom,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs" }, "facing=west,half=bottom,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "y": 180, "uvlock": true }, "facing=south,half=bottom,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "y": 90, "uvlock": true }, "facing=north,half=bottom,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "y": 270, "uvlock": true }, "facing=east,half=bottom,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "y": 270, "uvlock": true }, "facing=west,half=bottom,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "y": 90, "uvlock": true }, "facing=south,half=bottom,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs" }, "facing=north,half=bottom,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "y": 180, "uvlock": true }, "facing=east,half=bottom,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs" }, "facing=west,half=bottom,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "y": 180, "uvlock": true }, "facing=south,half=bottom,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "y": 90, "uvlock": true }, "facing=north,half=bottom,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "y": 270, "uvlock": true }, "facing=east,half=bottom,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "y": 270, "uvlock": true }, "facing=west,half=bottom,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "y": 90, "uvlock": true }, "facing=south,half=bottom,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs" }, "facing=north,half=bottom,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "y": 180, "uvlock": true }, "facing=east,half=top,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs", "x": 180, "uvlock": true }, "facing=west,half=top,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs", "x": 180, "y": 180, "uvlock": true }, "facing=south,half=top,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs", "x": 180, "y": 90, "uvlock": true }, "facing=north,half=top,shape=straight": { "model": "morematerials:stained_bricks_block_black_stairs", "x": 180, "y": 270, "uvlock": true }, "facing=east,half=top,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "uvlock": true }, "facing=west,half=top,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "y": 180, "uvlock": true }, "facing=south,half=top,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "y": 90, "uvlock": true }, "facing=north,half=top,shape=outer_right": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "y": 270, "uvlock": true }, "facing=east,half=top,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "y": 90, "uvlock": true }, "facing=west,half=top,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "y": 270, "uvlock": true }, "facing=south,half=top,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "y": 180, "uvlock": true }, "facing=north,half=top,shape=outer_left": { "model": "morematerials:stained_bricks_block_black_outer_stairs", "x": 180, "uvlock": true }, "facing=east,half=top,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "uvlock": true }, "facing=west,half=top,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "y": 180, "uvlock": true }, "facing=south,half=top,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "y": 90, "uvlock": true }, "facing=north,half=top,shape=inner_right": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "y": 270, "uvlock": true }, "facing=east,half=top,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "y": 90, "uvlock": true }, "facing=west,half=top,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "y": 270, "uvlock": true }, "facing=south,half=top,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "y": 180, "uvlock": true }, "facing=north,half=top,shape=inner_left": { "model": "morematerials:stained_bricks_block_black_inner_stairs", "x": 180, "uvlock": true } } } Normal stairs model example/template: { "parent": "block/stairs", "textures": { "bottom": "morematerials:blocks/stainedbricks_black", "top": "morematerials:blocks/stainedbricks_black", "side": "morematerials:blocks/stainedbricks_black" } } Inner stairs model example/template: { "parent": "block/inner_stairs", "textures": { "bottom": "morematerials:blocks/stainedbricks_black", "top": "morematerials:blocks/stainedbricks_black", "side": "morematerials:blocks/stainedbricks_black" } } Outer model example/template: { "parent": "block/outer_stairs", "textures": { "bottom": "morematerials:blocks/stainedbricks_black", "top": "morematerials:blocks/stainedbricks_black", "side": "morematerials:blocks/stainedbricks_black" } } Quirks Using Neighbor brightness - In your stairs block class, set the useNeighborBrightness property to true. Otherwise, you will get dark spots on neighboring bricks when you place the stairs. this.useNeighborBrightness = true; Model Registration - Like any other block in 1.8, the model has to be registered for display as an inventory icon. There are other posts on the subject, but essentially you need to do the following: Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register( item, metadata, new ModelResourceLocation( MODID + id, "inventory"));1 point