Jump to content

jabelar

Members
  • Posts

    3266
  • Joined

  • Last visited

  • Days Won

    39

Everything posted by jabelar

  1. Thanks TGG for continuing to blaze ahead to help the rest of us. In my tutorials I personally have taken the approach of not sharing fully working examples because I feel that a person only learns by struggling through the details of tying the concepts together, plus I expect you'll take on a lot of support requests as people copy and paste. But I'm also sure an example mod will be greatly appreciated. As an aside, I encourage all modders to develop a default starting code base for their mods, with all their favorite hooks and organization. When I start a new mod I can just copy my codebase and with a couple quick edits am up and running with working packets, event handling, etc. What TGG is developing here might work well for a lot of you. Anyway, my suggestions: - it is probably implied in your other topics, but custom network messages is good topic. - I personally like configurations. Not sure how many people use them though. I've even been getting into providing an in-game options GUI to control the configuration. - You mentioned terrain generation and dimensions, but specifically biomes, structures, trees, oregen are all pretty popular topics. - Villages would be interesting topic. - Achievements and stats. - Enchantments and potions. - Entities that are mountable is a popular topic.
  2. I have a tutorial on this here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-changing-drops-for.html
  3. One thing to consider is that metadata still (in 1. exists underneath the new Properties and IBlockState. However, according to diesieben07 the metadata is still apparently only 4 bits per block, so at most you can have 16 variations. it makes sense that it is still limited because there are millions of block positions in the world so the storage, memory and process all need to be compact. I believe the approach to use now is to make a PropertyEnum for your block which has a constructor like: PropertyEnum(String name, Class enumerationClass, Collection allowedValues) and also make sure to hook that into the block state and meta data values with the new standard methods. You might want to check out my brief tutorial on 1.8 Blocks here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-18-block-modding.html (although it seems you've already figured out a lot of the JSON stuff). While you can create a property that has more than 16 values, you have to provide a getStateFromMeta() and a getMetaFromState() methods which I assume need to be limited to 16 values. I can't find where that limit is enforced though. But otherwise, create an enumerated property up to 16 values and then that property gets mapped in your blockstates JSON files into different models, which in turn can be mapped to different textures.
  4. That's funny because that's exactly what I spent the weekend making. But yeah I didn't need a tile entity for it since like a crafting table the output was instantaneous. Some of the tricky things to think about with an un-crafting table: 1) Some crafting recipes produce multiple of an item (like 3 paper) so when you're uncrafting you need to decide what to do. Right now I have mine working so you have to put the same amount (or more) into the input for it to decraft. But my kids want me to make some exceptions, for example a door takes 6 wood to make 3 doors so they want 1 door to un-craft to 2 wood. I haven't coded that yet because it gets tricky -- there are some multiples that wouldn't work to divide the input like railroad tracks. 2) You need to consider the damage values in some cases -- like you want magenta dye to return the proper result different from the default dye. But damage values are also used on tools and weapons and armor to reflect actual damage, so you need to think through how to code this carefully. Once I get it working a bit better I might write a tutorial on an uncrafting table (I call it a "deconstructor"). But it sounds like you're taking the right approach.
  5. Yeah, I've been working a lot with custom block GUIs lately and I should probably write a tutorial. Like the question in this thread, the first thing is to understand the gui needs to have a container/inventory and secondly whether it needs to have a tile entity associated with it. Basically there are four possible scenarios: 1) Simple GUI without container or tile entity -- e.g. some sort of sign or simple information GUI that doesn't need player to put items in or out. 2) GUI with container but without tile entity -- if all the functionality of your GUI happens while the player is viewing the gui then you don't need a tile entity. For example a crafting table. 3) GUI with container and tile entity -- if you need to have the block do functionality even while player is not in GUI, like how a furnace will cook/smelt over time, then you should use a tile entity. 4) GUI without container but with a tile entity -- like maybe a machine that you turn on in the GUI and then it continues to do something after you exit the GUI. If you need an container then you need to associate it with something that implements IInventory. That can either be a separate class, or can be the tile entity (if you have one). Anyway, it sounds like you're just doing case #1. For that you just need a GUI class and don't need a container or tile entity class. Open the GUI just like you would in all cases -- in your block's onBlockActivated() method.
  6. As Ernio mentioned, using proxy is proper way to handle the case of classes that may not be loaded on client side. However, I successfully open custom GUI's on client side with just a world.isRemote style check. People have discussed that hear before, but sometimes the Java compiler cares if it sees a class it doesn't know at compile time, but in other cases it will only crash if the code executes (which it won't if you check for world.isRemote). So I suggest you first just check for world.isRemote before trying to call the displeyGuiScreen() method. Furthermore I checked and found that in my custom GUI I did not use an @SideOnly annotation, although it is a subclass of GuiScreen which does have @SideOnly. I'm not quite sure what the compiler does in that case, but it is quite possible that it is satisfied with my custom class. So try taking out the @SideOnly annotation from your GUI class if you have it.
  7. What happens to the blocks that are previously set while the entity moves? Do they automatically reset every tick, or will this leave a trail of lighted blocks? Also, does the light value setting work on air blocks?
  8. Okay, it definitely seemed like there was something missing. But interesting thing is my way (opening GUI on both sides) seems to work -- the gui displays, I'm able to move things around in the slots, and the contents of the slots is remembered each time I open gui and also remembered across saves. What's the downside?
  9. I always get tripped up on this when creating container blocks... I'm trying to make a simple mod that is essentially a furnace that doesn't need fuel. So I copied most of the furnace stuff (BlockFurnace, TileEntityFurnace, ContainerFurnace, GuiFurnace, SlotFurnaceOutput). The thing is that I'm having trouble with the onBlockActivated() method in the block class. If I write it like BlockFurnace (which calls displayGUI() only on server side) nothing shows up. If I call the displayGUI() only on client side, the GUI shows up but acts weird (understandably since server sync gets messed up). If I display gui in both server and client side it seems to work properly. To explain further, the vanilla BlockFurnace has: public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) { if (worldIn.isRemote) { return true; } else { TileEntity tileentity = worldIn.getTileEntity(pos); if (tileentity instanceof TileEntityFurnace) { playerIn.displayGUIChest((TileEntityFurnace)tileentity); } return true; } } But I can only get similar code to work if I also call gui to display on client side with something like this: @Override public boolean onBlockActivated(World parWorld, BlockPos parBlockPos, IBlockState parIBlockState, EntityPlayer parPlayer, EnumFacing parSide, float hitX, float hitY, float hitZ) { if (parWorld.isRemote) { // DEBUG System.out.println("BlockGrinder onBlockActivated() on client side"); Minecraft.getMinecraft().displayGuiScreen(new GuiGrinder(parPlayer.inventory, (TileEntityGrinder)parWorld.getTileEntity(parBlockPos))); return true; } else { // DEBUG System.out.println("BlockGrinder onBlockActivated() on server side"); parPlayer.displayGui((TileEntityGrinder)parWorld.getTileEntity(parBlockPos)); return true; } } How does the vanilla furnace get away with only calling display GUI on server side? Is this because the built in Gui classes have packets that sync them to client? Is my approach okay (it seems to work in sense that I can move things around between slots fine and the slot contents are remembered each time I open the gui)? I'm sure I'm missing something fundamental and always seem to get confused by this whenever I work with guis for containers...
  10. Thanks, I forgot about that. (It was still using launch wrapper.) I had updated on other computers, but not on this one.
  11. I just cloned one of my projects from github and ran gradlew setupDecompWorkspace and gradlew eclipse commands. Those commands seemed to run successfully, including the extractNatives step. However, when running it I got error about an unsatisfied link error for lwjgl. I checked on the build path settings for the lwjgl and they don't have any natives location listed. So I tried to manually associate them but found that there was no natives folder under my build folder. In all my other projects I have natives under the build folder. I don't know all that much about setting up workspaces, I pretty much have one set up that works that I copy for each new project. Anyway, what is best practice to ensure that all libraries are properly set up?
  12. Ahhhh, that makes sense.
  13. I don't know that much about ore generation actually. I concentrate most of my modding on entities and items. From briefly looking at the code, I think the idea is that the BiomeDecorator class has a method called generateOres() which posts the OreGenEvent.Pre event and then calls the TerrainGen.generateOre() method for each mineable type. This generateOre() method takes a WorldGenMineable parameter for each mineable type such as dirtGen, gravelGen, coalGen, ironGen, etc as well as the X and Z position. The WorldGenMineable has a generate() function which uses a bunch of loops to create clusters of the mineable type. The TerrainGen.generatOre() method is pretty much just a hook into the events. It creates the GenerateMineable event and posts it. The event is not cancelable, however it does have a result -- this means that it is possible for your event handler to give a Result.DENY to prevent the generation. I'm not certain but I think this would allow you to substitute your own ore generation -- give a DENY result but also call your own generation method. I'm sure there are good ore generation tutorials out there but I think you could try the following: 1) if you just want to add your own extra ore generation, you can just handle the OreGenEvent.Pre or .Post and call your own WorldGenMineable. 2) if you want to substitute your own and prevent some vanilla gen, then you'd handle the GenerateMineable event and send a DENY result, and also call your own WorldGenMineable. Anyway, look at the code in the classes and methods I mention above and it should give you some idea.
  14. You may need to think through the math of the getEntitiesWithinAABB() function. I looked up the call hierarchy and I'm suspicious that if the AABB you start with has minX = maxX, etc, which it will in your case, that maybe the code won't find anything. Like maybe you should try expanding the AABB a bit bigger to see if that finds the entity. If you get stuck you could consider the opposite approach. You can handle the LivingUpdateEvent and check for your tile entity underneath the entity. I think code like this should work for that: public Block findBlockUnderEntity(Entity parEntity) { int blockX = MathHelper.floor_double(parEntity.posX); int blockY = MathHelper.floor_double(parEntity.getEntityBoundingBox().minY)-1; int blockZ = MathHelper.floor_double(parEntity.posZ); return parEntity.worldObj.getBlockState(new BlockPos(blockX, blockY, blockZ)).getBlock(); }
  15. Weird. I definitely put in logs when typing (I know I did this because I was typing on a phone and it was small so I had to check to see that I actually put i and not l) but must have hit back or something. Yeah, I meant logs to access just one element of the array.
  16. Your getUnlocalizedName() method in your test tree item block doesn't seem right to me. You have: public String getUnlocalizedName(ItemStack itemstack){ int i = itemstack.getItemDamage(); if (i < 0 || i>= logs.length){ i = 0; } return super.getUnlocalizedName() + "." + logs; } Since logs is an array, don't you want logs? Also, for these sort of issues it is best to add some debug console statements. Like print out the return value to console to see if it is really what you expect.
  17. Yes there is a whole event bus dedicated to ore generation with the following events: GenerateMinable OreGenEvent.Pre OreGenEvent.Post Also, you can do block replacements during chunk loading events as well. I'm not sure how familiar you are with event handling, so if you are new to it you might want to check out my tutorial: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-event-handling.html
  18. I think for this particular use case (a minigame in a GUI) it is okay to go up to something like the Keyboard class and use the isKeyDown() method or similar. Since a minigame is basically intended to take over for a while it seems that it should be okay to intercept early on before processing through the Minecraft key processing.
  19. I have a tutorial for using the GuiConfig and IModGuiFactory functionality. It works mostly, although there is some not finished parts. Anyway, this tutorial might be interesting: http://jabelarminecraft.blogspot.com/p/minecraft-modding-configuration-guis.html
  20. I like keeping the number of event handling classes small because then it is less of a pain to register them and you won't forget to register one. To me having lots of separate classes is "messier" than having them all grouped in one handler. I do create a separate handler class for each bus though, so I have the regular one, the FML one, ore gen one, terrain gen one. So basically one handler registered to each bus. I suppose it depends on how complicated your event handling methods are. Most of mine are about 15 lines or less of code, so it is not too unwieldy to have them all in one class. As mentioned above, I don't think there would necessarily be any efficiency effect in the different approaches, although I suspect that having more classes means that the event bus needs to iterate more (would need a compiler expert to comment on that). But mostly it is a coding style preference.
  21. I have a tutorial on sound assets that you might want to look at: http://jabelarminecraft.blogspot.com/p/minecraft-forge-1721710-organizing-and.html
  22. I think one of the most important things when beginning with Java and/or modding is to learn to use your IDE (e.g. Eclipse) effectively. A good IDE will give flag the majority of errors, will give you good suggestions on how to fix things, and allow you to follow the call hierarchy back through the vanilla code. For example, in Eclispe in the preferences for java code style you can set it up so it will automatically insert @Override statements. I find this is really useful because it is very easy to write a method in your custom class which you think should override but you mess it up slightly essentially creating a different method that won't be called. You can also set up Eclipse to automatically put in imports, at least for the cases where it can uniquely resolve them, and take out unused imports. You can right-click on a method and choose "Call Hierarchy" and it will show you all the other code that calls the method. I highly suggest you spend a couple hours following the call hierarchies for the vanilla code -- like take a vanilla block class and select a method in its code and find out what calls it. This is hugely useful as a modder because the API isn't well documented so you often have to go into the vanilla code to confirm that it does what you expect. You'll also get a lot of coding ideas by exploring the code call hierarchies. You can right-click on any type, method or class and choose "Declaration" and it will take you to the code for that item. Anyway, I'm just saying to check out the various preferences in your IDE and learn to use it proficiently. Then you'll be able to correct most coding mistakes yourself without relying on the forum here!
  23. The code looks correct to me. So if it is only executing the outer loop that means the condition for the b<=highY must be false right away. Are you sure lowY is less than highY? Is it possible that your highY has a negative value?
  24. [quote name="Draco18s" post="147117" timestamp="1426176890"] It's called a for-loop. By the way, BlockPos now provides a cool function called getAllInBox() which returns an Iterable with all the BlockPos within a 3-D region. You'd still use a for loop to go through it, but coding-wise it is a bit cleaner to use an iterator for the looping as you don't need to nest the loops.
  25. Okay the most important rule in programming is that you need to look very carefully to ensure things are EXACTLY the same as you expect. If you look at your package explorer, it has BlockThing with a capital "B" and capital "T" but in the code that you circled it is blockThing only with capital "T". So from a programming perspective those are not the same thing, even if you maybe wanted them to be. Computer compilers are very literal -- even one little difference will have a different meeting. Based on your question, I have to suggest you need to learn some general Java programming first before you do Minecraft modding. I suggest getting a book called Java in Easy Steps as it is a book that can get you started on the main ideas of the programming language. Back to your specific question, in the code you circled at the right, you are basically "declaring" some fields to represent blocks and items. However, in that circled part at the top they are not actually set to anything because they are not initialized -- you need to assign them to a new instance of an appropriate class. The initialization comes down below where you have the = new ItemThing() and stuff. So that part is okay. Now you asked why the number of items/blocks doesn't match. Well if you look at where you assign the new instances, for things like ItemThingSoup you are making it a new ItemFood. ItemFood is a vanilla class so you don't need it in your own source. Depending on the way the classes are written, you may or may not be able to create more variations than classes. Like with ItemFood, you only need one ItemFood class but can make lots of different food items by changing the values you pass in the constructor and changing the texture name and such. You only need to create a new class if your functionality is different such that you can't use the customizations provided. But basically what you're asking about is basic Java programming and so you should take some time to read about that before trying to do much more modding.
×
×
  • Create New...

Important Information

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