Jump to content

one task, a hundred questions


Recommended Posts

hi guys.

i'm new to minecraft modding and a have a ton of questions. luckily, i need zero help with java itself.


i decided to make a set of small mods that modify the earliest stage of the game. i'll target both 1.8 and 1.7. some things went easily (like changing tool durability and making sticks drop from leaves), some things failed horribly (messing with achievements for example)...


the one task that caused the most frustration to me was making the player unable to break logs by hand. this will sound like venting/ranting (it is mostly venting) but i'll underline the actual questions:


first thing i tried was the BreakEvent; it is cancellable so the thing basically works... but the block visually disappears, the sound is played, and only then it is returned. am i wrong to see this as a bug in forge? why not fire the event earlier?


then i tried BreakSpeed; all sources on the net said - this is the thing. did anyone try to put a call that outputs a line into chat in there? (or into standard output, doesn't matter) not only is the message spammed several times per second while the block is being damaged (in gameplay sense), but spamming continues long after the block being broken. what's with that? wouldn't it be enough to set the mining/digging/chopping speed just once per attempt? and a natural question: why doesn't it stop when the player is done with the block and off to do something unrelated? back to topic, my initial test (the plan was newSpeed = original speed / 5000;) didn't work (why didn't it work? i placed "not remote" check at start, is that why it didn't work?) . anyway, i didn't dwell on why that event didn't work for me - i don't want to slow the game a single bit so i decided to skip the BreakSpeed event. not touching it with a stick. but while you're here, how much would using those "rapid fire" events slow the game down?


then i tried HarvestCheck. apparently not meant for what i need, moving on.


the PlayerInteractEvent also detects chopping logs with LEFT_CLICK_BLOCK action, and repeats many times until the block is broken, then stops. it is cancellable, but cancelling it doesn't stop or reset the chopping progress. maybe it works for right-clicking so let's skip this.


at that point i gave up on events.


next thing i tried was iterating through GameData.getBlockRegistry()... that seemed like a good idea. checked harvest tool, compared harvest level to 0... and the loop found zero blocks in total. apparently i was doing it too early. i don't see how FMLPostInitializationEvent is too early, but none of the blocks in the collection had harvest tool and harvest level set. fine, i tried WorldEvent.Load event - i managed to detect logs and stone there, called block.setHarvestLevel(tool, 1), launched the game and... it didn't work. this question is a bit vague but... is there a way that could've worked here? because i really wanted that to work - to set a few values on initialization instead of dealing with those events that seem to hate me.


i have a few more ideas to try but i think this is a point where i need to ask you guys for some pointers. i already wasted a few evenings (and i need to get to work each morning).


current plan is to detect chopping attempt in PlayerInteractEvent, save the block hardness in an internal collection, along with a number of ticks (40/20, don't know yet) and coordinates, then i'd set the hardness to -1. then, each tick, i would decrease tick counters  throughout my list and when one hits 0, i set the hardness back to original because the player will eventually try a proper tool and delete from the list. repeated PlayerInteractEvent hits for a block with coordinates in the list would reset the counter. and setting the hardness to -1 shouldn't mess up resistance like a large number would.


i expect that it would work, but that seems a bit complicated for the task at hand, and i feel i may have missed something with those events... also, for performance reasons, i wish to avoid doing things each tick. so, what do you guys suggest i do?


and i don't want to do things like damage the player to reset chopping or kick the player away from the tree - that is unintuitive and in case of knockback - a magnet for bugs.


i have considered a simpler alternative to the plan above - i could just set the hardness to -1 any time a block is hit by a bad tool or no tool and set the hardness to default value when hit by a proper tool (i can get defaults at game load); no ticking this way... the reason why i don't want to do this is that i'd leave around blocks with hardness of -1 and i'm worried about mod compatibility. yes the block can still be harvested (with proper tool), and it can still be blown up (i wouldn't touch resistance), but this would cause conflicts with any mod that checks block hardness. what do you guys think - am i right to worry here?


how would you guys solve my task?

Link to comment
Share on other sites



I would consult this handy reference guide, wrung from the vanilla code with much sweat, anguish and cursing:





but actually I think cancelling PlayerInteractEvent(LEFT_CLICK_BLOCK) should have worked.  Cancelling BlockEvent.BreakEvent should also have worked.  At least, it did in my testing.

You might be suffering some sort of client-server synchronisation problem - is your code executing on both sides?


One of the examples in this example project can be used to hook in to all the various block mining events, might help track it down.





Link to comment
Share on other sites

If you set the block hardness to -1, then no one, even with tools, will ever be able to harvest ANY of that kind of block. This is because blocks are singletons, so if you change a value for one, you've changed the value for all.


As for events like BreakSpeed - these do not of themselves slow performance by any noticeable amount, but if you subscribe to one and put it resource-intensive code, such as many nested for loops or recursion over a large area, then yes, you might cause some performance issues. If you keep your code lean, however, you likely won't notice at all.


BreakSpeed has to be called basically every tick because things may change - the player's tool may change, the block may change, the player may gain a potion effect or other change, etc. - and all of these may affect the break speed. If you just calculated it once, you wouldn't always have an accurate speed.


As TGG mentioned, LEFT_CLICK_BLOCK in the PlayerInteractEvent is a good bet, but the trouble with it is that it is only called on the server, so you may still get some glitches on the client.


To fix that, you'd need to subscribe to MouseEvent and KeyInputEvent (in case player changes the use-item key to non-mouse) - these both fire on the client; when they do, if it's the use-item key, check if the current mouseover object is a log block, check the player's current held item, and cancel the event if they don't match. This will prevent the player from clicking the block and starting to break it at all, which unfortunately will also prevent the animation.


Honestly, using BreakEvent, while it does give you that visual glitch where the block disappears briefly, may not be that bad. Annoyingly imperfect, but it gets the job done.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...

Important Information

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