jabelar
Members-
Posts
3266 -
Joined
-
Last visited
-
Days Won
39
Everything posted by jabelar
-
Well it first of all, you need code that checks all the block positions starting from the player position. However, note that as the distance gets farther the number of blocks required grows very large, so you will have to limit the range for checking to about 10 blocks for performance reasons. For the actually checking, you just loop through all the block locations using "for" loops for each of the x, y, and z dimensions and look for the block. Note though you need to check the distance of each of the target type blocks you find to see if you've actually found the closest. So the code would be something like this (I didn't check it, and it might need some modification, but you should get the general idea) Block targetBlock = Blocks.WHEAT; BlockPos closestPos = null; BlockPos checkPos = player.getPos(); for (int x = player.getX()-10; x < player.getX()+10; x++) { for (int y = player.getY()-10; x < player.getY()+10; y++) { for (int z = player.getZ()-10; z < player.getZ()+10; z++) { checkPos = new BlockPos(x, y, z); if (world.getBlockState(checkPos).getBlock == targetBlock} { // check if it is closer than any previously found position if (closestPos == null || player.getDistanceSq(player.getX() - checkPos.getX(), player.getY() - checkPos.getY(), player.getZ() - checkPos.getZ()) < player.getDistanceSq(player.getX() - closestPos.getX(), player.getY() - closestPos.getY(), player.getZ() - closestPos.getZ())) { closestPos = checkPos; } } } } } As you can see, it loops through all the combinations of x, y, and z within 10 blocks radius and checks if the block at that position is the type you're looking for. If it is, it checks to see if it is closer than anything else you've already found. There are actually cleverer ways of improving the performance, such as spiraling outwards and stopping at the first block found, but this is logically one of the most standard was to cover an area with a search.
- 1 reply
-
- 2
-
[SOLVED] [1.12.2] Replacing weather renderer, raining blood!
jabelar replied to Daeruin's topic in Modder Support
I think that field is being used to help animate the motion of the rain/snow. It is your class so you can just make your own field with the same name. But you'll also need to update it similarly so you'll need something like the updateRenderer() method. Also, note that there is also an addRainParticles() method you probably need to implement as well. -
[SOLVED] Trouble With Creating Block Similar To Minecraft Torch
jabelar replied to Spacejet's topic in Modder Support
These type of errors are usually do to typos. So the only way we can debug is for you to post your EXACT code. If you've edited it for modid then please re-post it. Otherwise, are there errors in your console? Is it complaining about a missing model, a missing model for a variant, or a missing texture? Or does it complain about a malformed JSON? Also, I noticed your model has a lot of cubes with repeated names. I'm not sure but maybe they need to be unique -- I know in the past tools like Techne would complain if you have duplicate names. -
[1.12.2] [Solved] Intercepting mouse input events
jabelar replied to GooberGunter's topic in Modder Support
Okay, I tried it out. The easiest way is to handle the InputEvent.MouseInputEvent and set the state of the keybind directly with code such as: @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) public static void onEvent(InputEvent.MouseInputEvent event) { GameSettings gs = Minecraft.getMinecraft().gameSettings; if (gs.keyBindAttack.isPressed()) // add your additional conditions here { KeyBinding.setKeyBindState(gs.keyBindAttack.getKeyCode(), false); } } Note that it must be the InputEvent.MouseInputEvent not the MouseEvent because the latter is called before the keybindings are updated during the Minecraft tick. Also, note that due to the weird way that the set state is implemented you also need to call the isPressed() method to ensure that any pressed counter is also cleared out. This is because there is both a pressed and a pressTime field which have to be cleared but the pressTime is private and needs the call to isPressed() to decrement. (Alternatively you could use Java reflection to access it directly). I tested it and it works well. All left-clicks on entities and blocks were prevented, but GUI interaction still worked. However, I guess you might still want to allow clicking on entities so you could check the mouse over function to make sure it was clicking on a block. There are alternative ways to do it. Like Choonster said, you could handle and cancel all the related events. Yet another way would be to create your own KeyBinding subclass that considers your conditions for blocking the keys, and replace the instances in GameSettings with your own version. -
[1.12.2] [Solved] Intercepting mouse input events
jabelar replied to GooberGunter's topic in Modder Support
Well, you could probably use the "keybinding" system which actually abstracts the mouse buttons as well. GameSettings.keybindUseItem (which is left button) has keycode -99 by default, keybindAttack (which is right button) has keycode -100 by default. keybindPickBlock (middle button) has keycode -98 by default. I think you could probably reassign the codes temporarily to some code that can never be pressed (not a valid keyboard code) or something similar. -
Weird. There are five things things that can go wrong, and I think you've covered them already: 1) lang file name is not capitalized properly according to the format. You're already aware of that, but just to check I would put two copies of your lang file in your assets, one with en_us.lang and en_US.lang, and see if that works. 2) lang file is in wrong directory. Your directory tree seems correct. Are you seeing it in your IDE properly or just in your file directory -- need to make sure the file is considered part of the project. May want to refresh or even re-run gradlew eclipse, confirm build path, etc. 3) your modid doesn't match for some reason. If your other assets work, then I guess that is correct. 4) your item unlocalized name doesn't match an entry in the .lang file. Is there something weird about the way you're setting or retrieving the unlocalized name for your items -- like could there be a weird unprintable character in it or something? 5 your .lang file has a weird character or unnecessary space (a space after the = will kill the matching). If you save the .lang file as UTF-8 make sure you choose option to save with BOM (byte-order mapping) or it won't be read properly.
-
[1.12.2] Lambda Expression Crashes - Overriding Run Doesn't?
jabelar replied to HalestormXV's topic in Modder Support
Yeah, this has been an issue for a long time with packet handling. I'm also not sure the explanation but isn't really a problem with your Lamba but can affect people doing non-Lambda as well. The code I actually use (I think it may be more comprehensive than Terrails example) in client proxy is: public EntityPlayer getPlayerEntityFromContext(MessageContext ctx) { // Note that if you simply return 'Minecraft.getMinecraft().thePlayer', // your packets will not work because you will be getting a client // player even when you are on the server! Sounds absurd, but it's true. // Solution is to double-check side before returning the player: return (ctx.side.isClient() ? Minecraft.getMinecraft().player : ctx.getServerHandler().player); } And in my server proxy it is: public EntityPlayer getPlayerEntityFromContext(MessageContext ctx) { return ctx.getServerHandler().player; } By the way, I know it is cool to have your IDE convert code to lamba, but in my opinion lamba only makes sense if you "think natively" in lamba and code that way from the start. If you're coding non-lamba and then getting your IDE to convert you're not really doing lamba (yet). But it is good for learning I guess. Also Eclipse can convert to lambda too, although maybe IntelliJ does something more with it. Like you can use the quick assist "migrate anonymous creations to lamba expressions" or you can have it do code cleanup with the "convert functional instances". -
Although he is coding in 1.7.10 (bad!) the concepts of tile entities and item stacks are general so I think it is okay to answer that. To add onto what Draco18s was saying... Tile Entities For performance reasons, the information about each block position as well as the amount of code that runs for each block must be purposefully limited. For example, in one chunk there are 65,536 (=16x16x256) block positions so in a given world it can quickly get to millions of block positions! So instead of having an object instance of block for every position, they have a single instance ("singleton" as Draco18s mentioned) for each block type and then just have a map that indicates the "block state" at each "block pos". Now since they wanted the blocks to be interesting, they allowed a little bit of data (4 bits of "metadata") that could be unique per block position to represent things like what growth stage a plant has, or which direction a furnace is facing, etc. That is all fine for static blocks, but what about blocks that are supposed to change like plants growing, leaves decaying, or furnaces cooking? Those things do require some code to run but they still had to be careful because things like leaves can still be very numerous. So they allowed some blocks to "random tick". Leaves and plants (and other things like water freezing to ice) do such random ticking. But that wasn't good for things like furnaces which needed continuous code to run plus needed more complex information such as inventories to be stored. Luckily things like furnaces are fairly rare, so for those they can have fully running code -- the fully running code is what a tile entity is. So basically, in order of increasing complexity you have: - Simple block with no properties (metadata always 0) - Block with properties (metadata) indicating type (like different logs) or other information (like rotation) - Block with random ticking to either adjust the metadata (like a plant growing) or to change blocks completely (like water freezing). - Block with tile entity, fully capable of complex processing (like smelting), animations and data storage. Item Stacks To understand this, you simply need to understand that the Item class really represents a type, and the ItemStack represents the actual item in the world -- meaning a type but also a quantity plus any special information like an enchantment or damage for that particular instance. Basically, an Item never really "exists" in the Minecraft world. Rather there are ItemStacks and the functionality of that ItemStack is defined by the Item in the stack.
-
There are some other things with your code you should probably change. There is a ModelRegistryEvent for the models. Also, each of the registries passes the actual registry in the event (in your case called "e") parameter so you should be passing that allong to your registerer methods and then those methods should obtain the registry from that. For example, you have But that should really be: public static void RegisterFood(RegistryEvent.Register<Block> e) { e.getRegistry().register(manaita); } Basically, you're assuming that you know what the registry is but you should really pass the actual registry along. Secondly, I think you're trying to be too clever by breaking up all the methods the way you are. I know it is nice to organize things into small dedicated methods but in this case you have to be very careful about the order of instantiation, registration, constructing and other initialization so it can be easier keep clear by keeping it together instead of hopping around between classes and methods. Lastly, you should move to the @ObjectHolder injection system for instantiating your singleton fields.
-
Although this particular structure seems to be rotation-agnostic (although I have a suspicion that the OP may want the actual resulting model to have a direction...) I just wanted to point out that for people who find it hard to think about making an algorithmic rotation they should just go ahead and do it with "brute force" -- just check for each rotated shape separately. I see so many people struggling with trigonometry or matrix manipulations to perform a rotation when you just need to check four shapes which you can do against pre-rotated pattern templates. Brute force methods are often less buggy and take way less time to program in the first place, but are often overlooked cause some of us like to be clever.
-
You're too impatient. In programming you build things up carefully step by step. This is the first step -- you logically need your block to have a property that indicates the direction, which you now have. Also you need to show your whole code. How can I help if I can't see if you also implemented the other methods for converting the property to meta data and back? Then, once you have the property working you still have many steps to take. You have to make sure your state responds based on what is surrounding it both when placing and if other blocks change around it, then you have to make sure your blockstate and model JSON files are correctly mapping your properties to the visual look. Anyway, next step should be to finish your block class. Make sure you have all the state to meta and meta to state methods implemented and post your WHOLE class code.
-
I just told you exactly what to do. You need the property stuff. Copy the PropertyDirection FACING part and also copy the method I already mentioned. Obviously the torch has such code and your block does not, so you should assume you might need it.
-
Okay, so by looking at BlockTorch I see that there is a property for which way it is facing. I think you should at least implement that -- there will be additional work to get it all working correctly, but the main point is your block has to have a location-based metadata (which is what a "property" represents) available to control the rendering and other behavior. Edit: You'll also want to implement the getStateForPlacement() method.
-
For the problem where they always point down, does that happen if you place the block in creative mode, or only when generated? I'll try to spend a bit of time looking at your code to see if I see anything.
-
Honestly world generation is one of the more complicated parts of Minecraft. The code is pretty convoluted with providers, generators, decorators, world gen, map gen, structures and so forth. But since you're in formal programming courses that should help. I'm not sure why you say "modify/override things inside a referenced library". You shouldn't have to do anything like that with Forge. Forge already has "hooks" to modify the vanilla behavior. Basically to modify things I approach it as follows: 1) look for public fields and methods you can modify directly. Because Minecraft is not properly encapsulated there are a lot of things you can access directly. For example, entity AI is in a public list so you can literally just clear the list and recreate your own. 2) look for events. Most of the common things people want to mod now have an event that helps you intercept the vanilla behavior and even fully replace it with your own. For example, you can handle the DecorateBiomeEvent to change how flowers or trees are generated. 3) use Java reflection. Since Java allows it, if necessary you can use Reflection to change the access permissions of fields and methods and then make use of them. I've started making a tutorial on world generation, although I admit it is a work in progress and it also isn't meant to be customizable like what you want. But it should be useful to you as I discuss most of the major classes involved. You can see it here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-1721710-biome-quick-tips.html However, after all that, what you are trying to do is probably fairly easy. I think you'd need to make a new WorldType so that would allow it to come up in the new world menu. Now it sounds like you don't really want to make it customizable but rather just random. So I think you can copy the customized dimension code but force the ChunkGeneratorSettings to have random values.
- 1 reply
-
- 1
-
I understand it takes a bit of time to get going. By the way did you know I have a bunch of tutorials to get people started? Check them out at http://jabelarminecraft.blogspot.com/. The problem is you have started with something (world gen) which is one of the tougher topics honestly, mostly because the vanilla code is pretty convoluted. For your particular problem though of the crystal only pointing down, the first thing to is look at how similar blocks behave. Like a torch or a fence that "senses" how it is placed to figure out how the model should look. Also, you really need to post code to get any significant help. Don't be too embarrassed (although Draco18s might make fun of you!) if your code is wrong. It is important for us to understand where you're really at and what kinda help you need. So at least tell me you've tried to research torches or similar and let us know what you've found about how they work.
-
I recommend learning how to use the debug tools to track problems down. You can use the debugger mode of Eclipse to set breakpoints and watch field values and you can use console or logger statements to help trace the execution. So in each of your methods, why don't you put a print statement to make sure it is executing and what the values are at the time of execution? Computers are fully logical so by simply observing the execution you will quickly find any problem.
-
It's not really right to keep asking for examples. This is your code and your mod and it is very rare that someone has done exactly what you want to do (and if they have then what is the point of you making the mod?). Everyone here learned by trying and so you need to to. Post the code that you have so far, explain the things you've tried (like looking at other blocks that do something similar when placed) and explain the steps you took to debug -- did you use debugger in Eclipse to track the block state, or did you print it out to the console? Those are the steps a person should do. Please post code and explanation of what you've discovered in your debugging.
-
I went ahead and logged an issue, maybe someone will create a hook for this in the future. https://github.com/MinecraftForge/MinecraftForge/issues/4756
-
Okay, basically Forge provides an event called InitMapGenEvent which is meant for exactly this sort of thing -- changing the way vanilla map gen happens. So you need to make an event handling method to handle that event. Then in that event you need to check if it is being fired for caves, so you can check if (event.getType() == EventMapGenEvent.EventType.CAVE) and if that is true then use the event.setNeGen() to your custom cave generator. For the custom cave generator, make a new class and copy all the code from the MapGenCaves class. Then depending on what you want to do, look at the code and figure out how to add your crystal blocks. That's pretty much it. Try the two steps -- handle the event and make your custom class -- and if you have trouble then post your code and we can help further.
-
[1.12.2] How to create a custom RendererLivingEntity client side
jabelar replied to Cospaia's topic in Modder Support
To modify vanilla behavior you often should consider using events. There is a RenderLivingEvent which allows you to replace the renderer. So what you can do is create your own player renderer class that copies the vanilla one but adds the text you want to add and then handle the event to use your renderer instead. So to start you need to learn how to handle events. I have a tutorial on this here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-event-handling.html I need to update the list of available events but most of the information should be good to get you started. Get an event handler working for RenderLivingEvent and have it check for player. Actually I think that event is generic so maybe you can just handle RenderLivingEvent<EntityPlayerSP> or similar. Then copy the RenderPlayer class into your own class and add stuff you want. Then make sure your event handler replaces the renderer with your own. Try what you can and post the code if you get stuck. We can help further then. -
You'd probably make your own map gen for caves to replace the vanilla one using the InitMapGen event. In your custom map gen wherever there is air next to stone you'd have a chance to place your crystal.
-
So I have a custom log that otherwise works well in game and wanted to register it in ore dictionary to act as same ingredient as oak logs. However, I'm not using the variants property from log but rather just have metadata value hardcoded to 0 for my log. But it doesn't seem to work -- no recipes are unlocked and if I place it in crafting table nothing happens. I tried registering the ore dictionary in both ways: OreDictionary.registerOre("logWood", new ItemStack(cloud_log, 1, OreDictionary.WILDCARD_VALUE)); and OreDictionary.registerOre("logWood", cloud_log); My log class is here: https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/blocks/BlockLogCloud.java Does someone know if this works -- using ore dictionary for matching vanilla recipe ingredients based on metadata? Or is there some other mistake I'm making? I realize I can work around this by creating my own duplicate recipes, but just thought I'd use ore dictionary where possible.
-
That does seem like it is a fairly parrot-specific piece of code. Would be good to have a Forge hook, although I'm not familiar with one. What would be nice is to replace the layer with a custom layer. However, that might be tricky since the render manager map and render player fields are private and/or final. If you use reflection though you might be able to figure out a way to insert your own layer. The concept would be to get access to the playerRenderer field in the Minecraft.getMinecraft().getRenderManager() and modify (again might need reflection) the list of layers by removing the entity on shoulder entry with your own. Since that seems tricky, maybe you can use events instead. I think the RenderLivingEvent is cancelable so you can handle it for player entities and replace the renderer with your version of the RenderPlayer class that has your custom layer. Or maybe someone has a much easier way?
-
Creating a crop (1.12.2) and gives wierd errors!
jabelar replied to UM3 F0R TH3 W1N's topic in Modder Support
I do admit that keeping up with latest version can be a bit of work, but it is worth doing and while a number of big things have been overhauled in recent versions I think it will settle down and everything is getting more modern/professional in their implementation.