Jump to content

jabelar

Members
  • Posts

    3266
  • Joined

  • Last visited

  • Days Won

    39

Everything posted by jabelar

  1. I just tried it with my code. Actually for 1.12.2 some of the methods have changed so it needs a bit of work. @diesieben07the code I posted was actually recommended by you in the past. I just updated it to 1.12.2 which was pretty easy -- just had to change some field accesses to the getters. However, two problems occurred. 1) The ExtendedBlockStorage now crashes if you use a get() where the Y-value is greater than 16. It seems that the index must be less than 4096 (16 * 16 * 16) so somehow the storage is now broken up into smaller pieces in the Y direction. However it is not clear to me how to then properly access the y values. 2) Concurrent modification errors can occur. What's the safe way to avoid that? I mean I understand that setting values in collections in certain cases can cause that, but that code isn't something I wrote -- there is no collection field in the modded code, I'm simply using the getters and setters provided. I'm guessing this is a bug? The setter should be thread-safe in my opinion. In any case it seems that something has changed with ExtendedBlockStorage (I'm assuming some performance improvements) that have made the ability for mod to use the getter and setter broken. What is the alternative?
  2. I really don't know how to do this. Well, in the loop for checking the layers you can do half the checking in one tick and half in the next. For example, you can check the world time and if it is odd just check the odd layers and if it is even just check the even layers. You also need a boolean to indicate when you've finished checking. So it would be like this -- in your event handler you'd have a static boolean called something like finishedReplacement which would intialize to true. Then in your PopulateChunkEvent handling method you would set finishedReplacement to false. Then you would also handle the ServerTick event and in that you would check if !finishedReplacement and then check if the world time is odd or even and then cycle through the layers accordingly. But before you do any of this, have you tried my original suggestion and confirmed how much lag it causes? It might be acceptable, especially if you don't process the entire chunk. Anyway there are LOTS of ways of working around performance issues if you think about it. For example, you could just process blocks that are within certain distance from the players. No need to check all the air blocks and bedrock locations within a chunk. By the way, blocks can be placed in the world by players too, so technically you probably need to also intercept block placement by handling the event and changing any placed farmland with yours. And if you allow creative mode then probably best to also make sure your farmland shows up and not the vanilla, although you can also leave it and substitute as the player picks it up.
  3. Using ItemStack#isEmpty is best because it checks for malformed Itemstacks as well (including somehow being null which can still happen in mods if modder uses old habits or code when emptying a stack).
  4. To debug this sort of thing is easy -- just put console (system.out.println()) statements in the code in judicious places and then see what gets printed. I personally put a print statement immediately before the if which prints out the value of every term, and then put a print statement in each path so I can confirm which path was actually executed. with that information it is very easy to see what is going wrong. For example one thing in your code is you're not checking which hand, so it is probably running for both hands, and maybe that is somehow screwing things up a bit.
  5. Yes, there is an example mod included in the MDK. I have a number of tutorials. Can't say they're the best, but I also link to some others. http://jabelarminecraft.blogspot.com/p/minecraft-forge-172-quick-tips-gl11-and.html Different tutorial authors focus on different topics, so for example I like entities whereas other people might have better stuff related to tesslators. Also, it is really tough keeping up with the new versions. I've converted much of my stuff to 1.12, and many concepts are still valid over other versions, but different tutorials have varying up-to-datedness.
  6. I'm not certain, but I think the matrix only applies to transformations (like translations, scaling, rotations). I'm not sure that the blending, colors and lighting are part of the matrix. I would try to save all the blending, color and lighting settings before you change them, then restore them at the end and see if that fixes is.
  7. I think you're still confused about how the information in the packets work. You shouldn't need a player field anywhere in the message. You just need to store the information you want to pass, which in your case should only be the speed. So on the server you should be calculating the speed, putting that in the packet and just sending that and storing it in a double field. But the double field shouldn't be in the message itself but rather some sort of global field that your rendering code can access later. So your fromBytes() method should store the value directly into some global field. Also, your rendering code is messed up as well because that code will only run on the client, but you're trying to send your packets from there. Also, you're looping through all the players but your packet is only containing information about one player. So let me try to break down the way the logic should flow. 1) on the server you should handle the server tick event and do a for loop through all the players and store the UUID and the speed (calculated) in a map type field. 2) on the server you should then cycle through each player and send a message to each player (send to all) that contains all the pairs of UUID and speed. Your toBytes() method should first put an int that indicates the size of the map, then write the UUID, then the speed, for each entry in the map. 3) on the client you should have a global field with same map format (UUID and speed). 4) on the client side you should handle the messages, and your fromBytes() should first read the int for the number of player entries, and then do that many loops to read the UUID and speed pairs into your map from step 3. 5) in your rendering handler you should find list of all players you care about (I guess you want the ones nearby) and then look up their speed based on their UUID from your map.
  8. You're passing a player parameter into your method, so why aren't you using that?
  9. Your packet isn't right. You have to remember that the tields in the packet are not transfered in the actual packet but rather used as the source/result for the to bytes and from bytes serialization. In your packet you read back the UUID but don't do anything with it. So other player will always be null. And more importantly you don't send the speed at all. You need to send that as well. What you need to do I think is take the UUID that you read and then look up the player entity based on that and then store that in your p field. Furthermore, you specifically make p an EntityPlayer so of course that is the type that you'll end up with. However, you code raises another question -- are you trying to display the speed of just the player on that client or are you trying to display speeds over other players that are in view? I thought you were just trying to display the user playerr's speed but it seems you are doing something with a bunch of "chaser" players. In that case what you really need to do is transfer over a map of speeds for all the entities in view. What I would do in that case is to serialize the packet as a map of UUID with speeds. Can you clarify what exactly you're doing with the speed information? In any case it is easiest to just get the client's speed information working first. So I would work on that.
  10. So your approach is generally correct. So the problem is in the details. To debug issues, you should really sprinkle console statements (system.out.println()) throughout your code in strategic places. For example, if you had such a statement in the onMessage() method you'd be able to confirm whether the message is even being received, and if it is you could see the values in the payload. So I would put in console statements within all the major methods, and wherever you have if statements also put some statements to help confirm which code path is being taken. The only thing that immediately stands out to me is that your event handler class you don't show any event handler annotation. Maybe you have it (you are only posting excerpts) but it is not enough to just register the class, the class also needs the annotation.
  11. What have you done so far? Have you created a custom block already? Show your code.
  12. Right, it only returns one biome but it returns it based on the BlockPos you pass to the method. So you return different biomes based on the position.
  13. Regarding the substitution system, it was broken for a long time, briefly I think it was working then it has been abandoned as far as I know. Regarding the performance of the replacement method, the reality is personal computers are getting way faster every year. On my computers (admittedly I have good gaming PCs) the method I used above is not noticeable. Also, if performance is a concern you can simply modify the algorithm to target more specifically. For example, the farmland should really be the top block so you don't need to check an entire chunk. If you just check a layer or two it should be invisible. And if you want to mitigate the lag you can distribute the checking over a couple of ticks. Lastly, in older versions like 1.7.10 most of the performance issues related to block placement were due to lighting updates. I think this is fixed now, but if really necessary you can edit the data in a more "raw" way rather than through the individual block placement methods and bypass the lighting update until the operation is complete. Personally I would just try my way first because you can pretty much cut and past, then modify the Y range to be more specific (maybe do top block instead) to make it faster. If it works for you like that then you're done. No point in worrying about something that might be a problem when you can confirm quickly whether it is an actual problem. Alternatively: if your block looks exactly the same then you can do other tricks. For example, you can just change it at the time a player interacts with it.
  14. If it is your own custom dimension you can just make sure your chunk generator generates what you want. Assuming you want to do this for vanilla or other mod dimensions then I've had success by handling the PopulateChunkEvent.Pre event. Something like this has worked for me in the past (in this example changing grass to stone): @SubscribeEvent(priority=EventPriority.NORMAL, receiveCanceled=true) public void onEvent(PopulateChunkEvent.Pre event) { // replace all blocks of a type with another block type // diesieben07 came up with this method (http://www.minecraftforge.net/forum/index.php/topic,21625.0.html) Chunk chunk = event.world.getChunkFromChunkCoords(event.chunkX, event.chunkZ); Block fromBlock = Blocks.grass; // change this to suit your need Block toBlock = Blocks.stone; // change this to suit your need for (ExtendedBlockStorage storage : chunk.getBlockStorageArray()) { if (storage != null) { for (int x = 0; x < 16; ++x) { for (int y = 0; y < 256; ++y) { for (int z = 0; z < 16; ++z) { if (storage.getBlockByExtId(x, y, z) == fromBlock) { storage.func_150818_a(x, y, z, toBlock); } } } } } } chunk.isModified = true; // this is important as it marks it to be saved } I last used this in 1.8 so possible some of the methods have changed in newer versions, but you get the idea hopefully.
  15. You're confusing the biome with the biome provider. A BiomeProvider has a getBiome() method which returns the biome for a given BlockPos. However, you've used a BiomeProviderSingle which always returns the same biome. So instead you should use a general BiomeProvider and @Override the the getBiome() method to provide the biomes that you want. In other words, the WorldType provides the BiomeProvider which provides the Biome instances.
  16. The fact is that the Forge fluid system doesn't enable any of the behaviors of fluid (drowning due to lack of air, pushing entities according to flow, coloring the world according to the fluid color when submerged, and so forth). The reason for this is that many vanilla classes specifically look for Material.WATER. So the easiest thing to do is to make sure your fluid has Material.WATER. This has some side effects though (map color will look like water) and as a modder you might not want all the behaviors -- like whether a sponge can soak it up, or whether it is swimmable. So I have created some tutorials on how to use events to overcome this and selectively add the fluid behaviors you want. Check out my tutorial here: http://jabelarminecraft.blogspot.com/p/minecraft-modding-custom-fluid-blocks.html I've also submitted a PR to implement this functionality in Forge directly, and it works well but I have some merge conflicts to fix but I've been traveling in Asia due to work and have other family obligations so realistically might not get it updated for another few weeks.
  17. Cool!
  18. Okay, but you still need to know Java and modding. You have not explained your ability, you have not explained exactly what you did, you have not posted your code, and you have not posted the errors. How are we supposed to help without that information?
  19. No, the server would send a packet to each client once a second with the speed (or average speed) for the associated player. The client would handle the message and update a static field that would be used to display speed in a GUI.
  20. Then just check for his/her username when you're processing the event.
  21. Was it averaging 5.2 or did you just see it occasionally. On a multiplayer server you will probably see a lot more variation due to lag. But on average it should be the same. And if the the server was running slower than 20 ticks per minute, I think the player would also move slower on average because the server would change the position each tick normally but would have less opportunities to change. On the client side though the speed can definitely jump more because the client will process movement in between server position updates. The server always decides the "truth" about the position, but in order to make movement seem smooth on the client the client will process movement as well but then jump to correct position when server packet with movement update arrives. To make the calculation smooth, the best way is to calculate it on the server and send a packet once per second (or some similar frequency) to the client that contains the calculated value. Alternatively, you could do it on the client but should average it over several ticks.
  22. So you got rid of the global id registration? Regarding the spawn egg, in 1.7.10 you need to create a custom egg (actual class for egg is called monster placer). See my tutorial link below on how to do that. I have an open source mod for 1.7.10 with multiple mobs. Feel free to adapt it to your needs here: https://github.com/jabelar/WildAnimalsPlus-1.7.10. I also have tutorials on custom entities here: http://jabelarminecraft.blogspot.com/p/creating-custom-entities.html
  23. No because I start at -1.
  24. Just compare each item in the inventory with the one you want and if it is in the inventory copy it.
  25. Okay, the stack overflow error is a bit weird at that line of code. I looked through your code and one thing that stands out is that you're double-registering your entities. You shouldn't use the global id registration. At the time of 1.7.10 they were transitioning from the global registration to per-mod id, but you should only use the mod id one. Furthermore, you don't need to set it based on the getGlobalUniqueID(0 method, but rather simply start at 0 for your mod and increment for each one. For example, in my mods I had something like this: protected int modEntityID = -1; public void registerModEntity(Class parEntityClass, String parEntityName) { EntityRegistry.registerModEntity(parEntityClass, parEntityName, ++modEntityID, WildAnimals.instance, 80, 3, false); } You'll note that I use a pre-increment ++ on the id so that if this gets called multiple times it will get the next id for next entity registered. I'm not sure but potentially the double-registering of your entities could cause some problem during rendering so maybe clean that up and see if it helps.
×
×
  • Create New...

Important Information

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