Welcome back, and yes! This time it’s finally actually on Saturday! From the survey last time, it looks like it’s more fun to have a longer post with more details, so I’ll be trying that out again today! I also got a recommendation to actually use these mystical things called paragraphs… hopefully this one should be easier on the eyes. Today what I’ll be talking about is smaller things, but (hopefully) still interesting. Alright, let’s hop into it! <h2 class="heading">The Beast</h2> <p class="paragraph" markdown="1">The first part of the post is mutants. Specifically, I’m going to start off with The Beast, which as I’ve explained before, is a Wither-Ravager mutant. For most of the other zones in ReLife, there is a sort of warning before it actually starts. For example, Blood Rain only shows some of the particles for a little, and only starts damaging you when the rest of the particles come in. Lightning Storm has it striking the large tree before striking randomly. For The Beast, I added a ravager roar noise, during which The Beast is frozen with no AI (it doesn’t move or attack or anything). That was pretty simple to implement, simply looping through all the players and playing the noise for.

The second thing I wanted to change on The Beast, is that sometimes when the ravager roared, it would hit the wither it was riding and shove it at ~90 blocks per second away. For context, a ravager roars after it is done being stunned, and it has a 50% chance to be stunned after you block one of its hits with a shield. When it roars, it shoves all the entities around it depending on how close they are to the ravager, and since the wither is riding the ravager its velocity increases dramatically. Anyway, I was concerned when The Beast literally disappeared in a puff of smoke, then came crashing back through literal bedrock. Anyway, the way I ended up fixing it was fairly simple. I added a listener for when ravagers roar, and then if the roar hit any entities with the tag “beast” (such as the wither), it would set that entity’s velocity to zero. How I get what entities the roar hits is by checking all the entities in the radius of the roar, which I got simply by looking through a few NMS classes. The reason this took a little longer than it should have was because I originally just tried cancelling the damage to the wither, thinking it was being sent flying by knockback, when in reality I had to deal with the roar event. All told, fairly small fix.

Beeper Swarm

Alright, next part of mutants; Beepers. Beepers are bee-creeper mutants, specifically creepers riding bees with enhanced speed. Similar to The Beast, for Beepers I wanted to have some sort of warning sign. What I ended up going with was at each Beeper, it would create the noise of a bee buzzing angrily, with double the range. So, as long as you are within ~30 blocks of a Beeper you will hear an angry buzzing sound, and considering there are (currently) 5 per chunk, you’ll probably be in range of a couple.

Again similar to The Beast, there was one other issue I was having with Beepers. You may have asked this question yourself upon hearing what the Beepers were, but what if you just block yourself off with some dirt? The creepers won’t be able to see you to explode! With The Beast this isn’t an issue because it can simply ram through any blocks. For the Beepers however, I wanted them to explode - but only if their pathfinding doesn’t have a way to reach the player. Unfortunately that’s easier said than done. Thus begain the constant struggle of sifting through NMS. Now I’m going to try to explain how pathfinding works in Minecraft, without going into too much of the nitty-gritty code stuff.

Now, I don’t entirely know how the path is created in the pathfinding, because I think I’m missing some source code or something, but I do know how moving along said path works. Essentially, every EntityInsentient (as far as I can tell, every entity except players), has a NavigationAbstract, which is the navigator/pathfinder. That navigator contains a PathEntity, which it initiates from a path (again, I don’t know how that path is created as I cannot find where a particular function is called). That PathEntity has a list of PathPoints, which as you might guess are points along the path, a list of PathDestination (I don’t know why it’s a list), which are specialized PathPoints, and a position in its list of points. The navigator increments the position, gets the point, and then moves the entity to said point. Now remember my goal: to detect when the navigator cannot reach its target. The final nail in the coffin of that idea is the fact that rather than having a constant long path from the entity to the target, the navigator often has many smaller paths.

Ok, new plan. If the navigator has a target (and it only has a target when it’s targeting a player), and it’s at the end of the path (which is theoretically only when it has ran out of room to go towards the player), have the Beeper explode. Now this worked fairly well, but when I encased myself in dirt in order to test them, by the time they broke through to the dirt, there weren’t many left. I assumed that this was because there were many Beepers exploding when they shouldn’t have, so I went down a rabbit hole of attempting to refine my explode condition. I spent a long time on that, and it ended up being entirely useless as the only reason they were dying was because the Beepers would cluster up and then explode, killing each other. Simple health boost later and… yup, everything seems to be in order. Beepers done (for now)!

Blood Rain

Alright, on to fluids! Just like with the mutations, I’ll begin with the easier one. This will be real short, essentially I just wanted to have Blood Rain degrade any armor you’re wearing. Simply, in the loop that damages players inside the rain, it degrades all of the armor the player is wearing. The only catch was if you had an empty armor slot it would throw a null exception, but that was a simple fix.

Poisonous Fog

Alright, now this one is a bit more complicated. Not as difficult as figuring out pathfinding, but multiple magnitudes more difficult than damaging armor. The basic idea is that if you right click with a glass bottle whilst standing in poisonous fog, you can bottle it similar to collecting dragon’s breath. After collecting it, you can either throw it on the ground and create a small patch of fog, or apply it to arrows and create poisonous fog tipped arrows (arrows with effects on them). First part is being able to collect the death fog in a bottle in the first place. Essentially, I have a listener for player interact events, and then if the player is right clicking, is inside poisonous fog, and is interacting using a glass bottle, then continue. Unfortunately, the Spigot API does not have a method for giving an item to a player, but if their inventory is full then dropping into the world, which I think they should add. Fortunately, when you add an item to their inventory, it does return a list of items that don’t fit. I simply made a util function that adds the item to the inventory, then loops through the returned list of items and uses an NMS function from players to drop the item. Next, I had to deal with removing the glass bottle. I started by simply decrementing the count of the held item (which has to be glass bottles) by one, which worked, however a funny thing happened if you only had one bottle. It would remove the bottle (set the count to zero), but then it wouldn’t give you the bottle of fog! For some reason, when you set the count to 0, and then add an item to that slot, I believe the count remains at 0. I don’t know why, but I just added an if statement so that if the count is one, instead of decrementing the count to zero, I simply set the item in the inventory to null - empty slot. That took more tinkering with than I’m going to write about, but that’s just because it was a whole bunch of debugging and trying slightly different solutions. Last thing was making it look like you are using the bottle, but that is just sending an animation packet.

Alright that was a long paragraph, sorry. Part one complete - if you right click with a glass bottle, it will give you a lingering potion bottle with a custom color (same as the poisonous fog) and name. Next step is dealing with when you throw the lingering potion to create a small cloud. Thankfully, there is an event for creating area effect clouds (the entity that lingering potions create), which allows me to edit it. Also thankfully, the API allows me to edit the particles that the clouds create! Usually they are circular potion particles, but I could change them to be the same as the poisonous fog. Last step to making it work is starting a loop that exits when the cloud dies (because the cloud is technically an entity), that simply loops through the players and if their bounding box overlaps with that of the cloud, damage them the same as the poisonous fog. Thankfully enough, that worked pretty much first try, with only a few minor issues to fix. <p class="paragraph" markdown="1">Ok, last part of the post: poisonous fog tipped arrows. In minecraft, if you surround a lingering potion with 8 arrows in a crafting table, you get 8 tipped arrows with the same effect as the potion. When you shoot someone with those arrows, that effect is applied. Unfortunately, since the poisonous fog isn’t actually an effect, I have to have a custom recipe in order for the tipped arrows to have the right coloring and data. Well, little bit of sorting through different events later, and I arrived at the event for when it is loading a recipe into the crafting table. Essentially, whenever you put an item in or take an item out of the table, this event is called, which allows you to modify the result of the recipe. Simple next step is that if the outcome is a tipped arrow, and it is using a bottle of death fog, modify the output to be a tipped arrow with the correct color, set the custom name, and hide the potion effects so the lore of the item doesn’t say “No Effects”. Next is very similar to with the lingering potion, when the arrow hits someone, start a loop to damage them as appropriate for poisonous fog. The final issue is that as a custom tipped arrow, when you pick it up it won’t have the custom data. Once again there is a nice and easy API event to patch into for players picking up arrows from the ground, and voila! Everything works as intended. Poisonous fog tipped arrows complete!

Wrapup

Sorry if the last part felt a bit rushed, it’s starting to get late, but thank you all for reading through once again. I really enjoy writing them more drawn out and going a bit more in depth, and I hope it’s more entertaining to read. This past week there were more little things than big bits to work on, but since this week is Thanksgiving break and I don’t have any plans, I hope to be able to get a lot of work done. As always, see you next week and have a wonderful Thanksgiving!