Jump to content

Kinniken

Members
  • Posts

    266
  • Joined

  • Last visited

Everything posted by Kinniken

  1. Never mind, I should have tried first, got the class via a google search.
  2. Hi jalebar, I was going through your tutorial again because your generic trigger mechanism would be perfect for my needs, but the code you posted in your tutorial is broken, it even has syntax errors (maybe encoding issues), for example: private final Set> listeners = Sets.>newHashSet(); I could fix quite a lot of them with a bit of guesswork but not all. Would it be possible for you to post the actual class? Thanks!
  3. I had actually checked your tutorial, one of the first thing I do for new features I just didn't know if it was up to date to changes in Forge, like that merge of Moar Advancements (if it changes anything to it). I was indeed looking for something code-based, I'm not a big fan of overly complicated JSON triggers. And if I can use this occasion for a small bit of feedback on your very useful tutorials, could you add the date at which a tutorial was written? It's often really useful to know if it's recent or not.
  4. Hi all, I need to define items in external config files for reference in my mod's content files. Until now I've done this simply enough in the following way: wool_black;minecraft:wool;15 wool_blue;minecraft:wool;11 wool_brown;minecraft:wool;12 wool_cyan;minecraft:wool;9 wool_gray;minecraft:wool;7 wool_green;minecraft:wool;13 Where the first value is an internal name for my mod and the next values are the Minecraft item name and the meta value. Works very well except for items dependent on item-stack level NBT data. Is there any way of storing (simple) NBT data in single-line string format that I could use rather than code mine? Obviously not for really complicated data structure, but say to store the data needed to define a potion for example? Thanks
  5. Hi all, I've been reading up on adding advancements in 1.12 and it seems like recommended practices have shifted quite a bit since the first Forge releases. I'm specifically looking for advancements triggered by custom triggers in code, plus maybe some inventory-based ones for a few cases. Is there a good tutorial or model with the clean way of doing this now? Thanks
  6. Actually, I needed both to override getRenderType and to have that empty TESR, otherwise the TESR of the vanilla bed gets used on top of my block's rendering. But of course that's only because I'l extending a vanilla block with a TESR.
  7. Thanks! That last part was indeed exactly what I was missing.
  8. Hi all, I am adding custom beds to my mod, that unlike the regular ones will display as low-lying blocks, think half-slab or a little smaller (this is intended to represent beds like Japanese futons or simple hay beds etc). I could try and copy vanilla and have beds using tile entity rendering, but that seems unnecessarily complex and CPU-intensive for my purpose when block-based rendering is more than fine. I tried extending BlockBed, extending TileEntityBed, and declaring an empty TileEntitySpecialRenderer for my custom TileEntity, but it stills overrides the block-based rendering - my bed is not displayed at all. Any way around that? I know some blocks with tile entities still use normal rendering (like furnaces). My bed block: public class BlockMillBed extends BlockBed { public BlockMillBed(final String blockName) { super(); setCreativeTab(MillBlocks.tabMillenaire); setUnlocalizedName(Mill.MODID + "." + blockName); setRegistryName(blockName); } @Override public TileEntity createNewTileEntity(final World worldIn, final int meta) { return new TileEntityMillBed(); } @Override public boolean isBed(final IBlockState state, final IBlockAccess world, final BlockPos pos, @Nullable final Entity player) { return true; } } My empty tile entity: public class TileEntityMillBed extends TileEntityBed { } Empty renderer: public class TileEntityMillBedRenderer extends TileEntitySpecialRenderer<TileEntityMillBed> { } Block and TE registration: event.getRegistry().register(new BlockMillBed(MillBlockNames.BED_THATCH)); GameRegistry.registerTileEntity(TileEntityMillBed.class, Mill.MODID + ":" + MillBlockNames.BED_THATCH); And renderer registration: ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMillBed.class, new TileEntityMillBedRenderer()); Oh and I've of course added a block state, bed_thatch.json: { "multipart": [ { "apply": { "model": "millenaire:bed_thatch" }} ] } And a block model: { "parent": "block/half_slab", "textures": { "bottom": "millenaire:blocks/thatch", "top": "millenaire:blocks/thatch", "side": "millenaire:blocks/thatch", "particle" : "millenaire:blocks/thatch" } } Any ideas? Thanks!
  9. Never mind, it works. I had a naming mistake. If anyone checks this out later, the example above is fine.
  10. Hi, I am trying to implement new glass panes, basically identical to the coloured glass panes except that I have a variant attribute instead of a colour one since I'll be putting patterns on mine. I've extended BlockPane and essentially copied the BlockStainedGlassPane code only adjusting for the property difference (for now my variant property has only one possible value, "white"). I'm having issues getting the blockstate and/or the models to work. On startup I get this error: [19:33:27] [main/ERROR] [FML]: Exception loading model for variant millenaire:stained_glass#east=true,north=false,south=true,variant=white,west=false for blockstate "millenaire:stained_glass[east=true,north=false,south=true,variant=white,west=false]" net.minecraftforge.client.model.ModelLoaderRegistry$LoaderException: Exception loading model millenaire:stained_glass#east=true,north=false,south=true,variant=white,west=false with loader VariantLoader.INSTANCE, skipping at net.minecraftforge.client.model.ModelLoaderRegistry.getModel(ModelLoaderRegistry.java:153) ~[ModelLoaderRegistry.class:?] at net.minecraftforge.client.model.ModelLoader.registerVariant(ModelLoader.java:248) ~[ModelLoader.class:?] at net.minecraft.client.renderer.block.model.ModelBakery.loadBlock(ModelBakery.java:153) ~[ModelBakery.class:?] at net.minecraftforge.client.model.ModelLoader.loadBlocks(ModelLoader.java:236) ~[ModelLoader.class:?] at net.minecraftforge.client.model.ModelLoader.setupModelRegistry(ModelLoader.java:163) ~[ModelLoader.class:?] at net.minecraft.client.renderer.block.model.ModelManager.onResourceManagerReload(ModelManager.java:28) [ModelManager.class:?] at net.minecraft.client.resources.SimpleReloadableResourceManager.registerReloadListener(SimpleReloadableResourceManager.java:132) [SimpleReloadableResourceManager.class:?] at net.minecraft.client.Minecraft.init(Minecraft.java:559) [Minecraft.class:?] at net.minecraft.client.Minecraft.run(Minecraft.java:421) [Minecraft.class:?] at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_73] at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?] at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_73] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_73] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_73] at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_73] at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?] at GradleStart.main(GradleStart.java:25) [start/:?] Caused by: net.minecraft.client.renderer.block.model.ModelBlockDefinition$MissingVariantException at net.minecraft.client.renderer.block.model.ModelBlockDefinition.getVariant(ModelBlockDefinition.java:83) ~[ModelBlockDefinition.class:?] at net.minecraftforge.client.model.ModelLoader$VariantLoader.loadModel(ModelLoader.java:1189) ~[ModelLoader$VariantLoader.class:?] at net.minecraftforge.client.model.ModelLoaderRegistry.getModel(ModelLoaderRegistry.java:149) ~[ModelLoaderRegistry.class:?] My blockstate looks like this, copied and adjusted from white_stained_glass_pane.json : { "multipart": [ { "apply": { "model": "millenaire:stained_glass_white_post" }}, { "when": { "variant":"white", "north": true }, "apply": { "model": "millenaire:stained_glass_white_side" } }, { "when": { "variant":"white", "east": true }, "apply": { "model": "millenaire:stained_glass_white_side", "y": 90 } }, { "when": { "variant":"white", "south": true }, "apply": { "model": "millenaire:stained_glass_white_side_alt" } }, { "when": { "variant":"white", "west": true }, "apply": { "model": "millenaire:stained_glass_white_side_alt", "y": 90 } }, { "when": { "variant":"white", "north": false }, "apply": { "model": "millenaire:stained_glass_white_noside" } }, { "when": { "variant":"white", "east": false }, "apply": { "model": "millenaire:stained_glass_white_noside_alt" } }, { "when": { "variant":"white", "south": false }, "apply": { "model": "millenaire:stained_glass_white_noside_alt", "y": 90 } }, { "when": { "variant":"white", "west": false }, "apply": { "model": "millenaire:stained_glass_white_noside", "y": 270 } } ] } I've created the models referenced, again using vanilla's white stained glass frame as a reference. Here is the post one for example : { "parent": "block/pane_post", "textures": { "edge": "blocks/glass_pane_top_white", "pane": "millenaire:blocks/stained_glass_white" } } Any idea what is going wrong? I don't understand how in vanilla each colour has its own blockstate with no obvious mapping anywhere, is the issue related to this? Thanks K.
  11. Haven't looked at those classes in particular but I know what you mean.
  12. Ah, that's a bit disappointing. Reimplementing everything from scratch just to change some marginal behaviour? Ah well.
  13. Hi all, I would like to know if there's a guide or an example I could follow with the best practice on making a custom furnace in 1.12. I pretty much need something that works like the vanilla one, except : - only takes in wood as fuel - burns slower - placement is not directionnal Should I be extending the default one or making something from scratch? If I have to make my own block, should I extend BlockContainer or Block directly? I've heard bad things about BlockContainer... Thanks for any pointers. K.
  14. Thanks guys, that helped, got it working with no other issues based on Draco's examples. The label and desc are not required for those advancements right? They don't seem to show up anywhere.
  15. Bullseye. I had never noticed, but it actually implements several texture variations of many blocks, and for stone and a few others, none have the default name. Well, little I can do about that, too bad.
  16. I guess I should have posted this instead
  17. Good point about grass... Another small thing, I have it in place and it works fine, however I'm running a 64x texture pack. For some blocks, it's taking the texture from the pack, for some, it's taking the Minecraft one. For example, this one uses the 16x texture: { "parent": "millenaire:block/source", "textures": { "sourceblock": "minecraft:blocks/stone" } } And this one the 64x one: { "parent": "millenaire:block/source", "textures": { "sourceblock": "minecraft:blocks/gravel" } } Whether the overlay is 16x or 64x from a custom resource pack doesn't seem to make any difference.
  18. Thanks, that works! However, that means that blocks rendered that way have the performance cost of partly-transparent blocks even if they are actually totally opaque?
  19. Hi all, I'm trying to have a block that renders with two textures on each side, a background layer and an overlay that's a partly-transparent PNG. From what i read online I figured this should work: Base model: { "parent": "block/block", "textures": { "overlay": "millenaire:blocks/source_overlay", "particle": "#block" }, "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#sourceblock", "cullface": "down" }, "up": { "texture": "#sourceblock", "cullface": "up" }, "north": { "texture": "#sourceblock", "cullface": "north" }, "south": { "texture": "#sourceblock", "cullface": "south" }, "west": { "texture": "#sourceblock", "cullface": "west" }, "east": { "texture": "#sourceblock", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#overlay", "cullface": "down" }, "up": { "texture": "#overlay", "cullface": "up" }, "north": { "texture": "#overlay", "cullface": "north" }, "south": { "texture": "#overlay", "cullface": "south" }, "west": { "texture": "#overlay", "cullface": "west" }, "east": { "texture": "#overlay", "cullface": "east" } } } ] } And the actual model: { "parent": "millenaire:block/source", "textures": { "sourceblock": "minecraft:blocks/stone_granite" } } (The intention being that the overlay is always the same, but the background texture can change for different blocks) In practice all that shows my overlay on a white background, despite it being a PNG with a transparent background. Any ideas? Thanks!
  20. Hi All, I have a few recipes in my mod that use custom items and Minecraft items. For example, this one: { "type": "minecraft:crafting_shaped", "group": "chickencurry", "pattern": [ "T", "C", "R" ], "key": { "T": { "item": "millenaire:turmeric" }, "C": { "item": "minecraft:chicken" }, "R": { "item": "millenaire:rice" } }, "result": { "item": "millenaire:chickencurry" } } They work fine, my only issue is that they only appear in the recipe book once the player has used them at least once. I would prefer it if they could be discovered whenever he gets either of the custom item involved. Is there anyway of specifying this with JSON-based recipes? Thanks
  21. 5 MB per path. On a server with several active villages with say 20 villagers each, it adds up fast. Plus my other threaded uses. You're right though, my setup is also vulnerable to Minecraft upgrades, but much less so. Ultimately my adherence is only to one method testing whether a chunk is loaded or not, not to the detailed chunk implementation that making copies would require. And I'm not ignoring the problem, I'm making a choice with a know risk that has a very, very low occurrence, that of reading four bytes of sequential data and assuming there won't be a write operation in the meantime. Anyway, thanks again for the technical help, but ultimately I have to prioritise my development work, and unless players start having threaded problems again I'm considering this issue closed.
  22. Ok, that is faster than I'd have thought. Still, that's a lot of extra RAM usage, and more importantly, a fairly complicated new dev with strong adherence to yet more Minecraft classes, meaning yet another bit of code that can go wrong in upgrades. Thanks for the detailed information. Should my current approach prove problematic for players, I'll look into doing a copy from the main thread instead.
  23. Regarding the fact that I'm not guaranteed to see an updated value after a write operation, you are right, that's a limit of how maps work in Java. However that's not an issue in my use case - sure a path I'm calculating could be made obsolete by a block being placed 5 ms before I run my calculation, but it also could be made obsolete by a block placed 5 ms after. That's why paths need to be recalculated periodically, or in case an entity gets stuck. For the issue of reading partially-saved data, as far as I can see in the MC code, the bytes that actually represent a block and its meta value are set and read together, sequentially. So the potential problem would be for me to do a read while only part of the four bytes that represent a block state have been saved. Not impossible, but... Against that, if I want to calculate a path between coords say 100 blocks away, I need to analyse an area of something like 7*7 chunks. I'm willing to time it, but the memory and CPU usage of duplicating 49 chunks to calculate a path doesn't seem that trivial. Anyway, I'm not going to stick to "5 minutes of testing", I have enough testers running the mod for hours that if threading crashes do reoccur I'll know about it.
  24. The problem was not me directly modifying collections, the problem was me forcing Minecraft to load chunks by trying to read block states in them, and doing that can modify collections - the entity list in particular, since loading a chunk causes entities that were in it to be loaded. So yes, even if your own code does nothing to do with collections or entities, chunk loading is definitely not thread-safe. And Minecraft does basically no threadsafe locking, which is why using threaded code in Minecraft is dangerous
  25. Making copies of entire chunks would kind of defeat the purpose, which is to optimize performance... I've checked with several modders, everyone who worked with threaded access agrees that accessing block states in loaded chunks is thread-safe. I've looked at the Minecraft code, it indeed implies only reading from two hash maps (the one with loaded chunks and the one with block states within a chunk), and read-only operations on maps are thread-safe in Java. I've now updated my mod to validate that a chunk is loaded before doing any reading of block states in it, and since then neither me nor other testers have had those crashes. The only problem I could see is if I did a read access on a chunk that got unloaded between my check and the read. And since I do those two operations immediately one after the other that seems like a negligible risk. Unless players start reporting threading crashes again I'm considering this closed.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.