SurviveTheNight

The server is currently offline.

Connect now using the IP mc.survivethenight.net

Internet Explorer

Internet Explorer is not supported. Please upgrade to a more modern browser.

Major Loss of Performance

STN is currently having a major loss of performance, we are still investigating!

Devlog Devlog #4 - STN Creatures #1
Started by SurviveTheNight

SurviveTheNight

SurviveTheNight

Administrator
Joined
07 Feb 2023
Last Seen
15 Dec 2024
Topics
36
Posts
36

Hi!

This is the fourth devlog! In this thread I will talk about our creatures system, how creatures work in STN and what has changed (so far).

Introduction

Welcome to the first devlog about creatures. Atleast one more devlog about creatures follows after this!
Today I will introduce you to creatures in STN, how they work, what we have changed so far and what features might come up in the future!
I will not cover boss monsters in this devlog, there will be a seperate one specifically for those in the near future.

Minecraft Entities

Before talking about our creatures specifially, I want you to understand how entities and livingentities work in spigot (the server we are working with basically).

Let's talk about Ironic Golems for example - the annoying iron golems you may spawn by mining ores, that deal far too much damage and shoot iron bolts at you, do you remember?

You may have noticed: They attack you by default without you having to hit them and they also only attack you. No other players, not even other enemies like vanilla iron golems would do.

The Spigot API provides a set of very useful methods, especially when working with entities in minecraft. For example you can spawn them in at certain locations, give them a name, set certain attributes such as setRemoveWhenFarAway() (this basically allows you to keep entities where they are even when the chunks are not loaded) and much much more.

However there are almost no methods to properly change the AI of those creatures!
And now NMS comes into play!

What is NMS? NMS stands for net.minecraft.server and is basically a bunch of code provided directly by Mojang and contains all the important stuff such as server packets, client packets and everything else that's happening on the server.

Working with it allows you to do many many more things compared to the spigot API due to that API being very limited at the time of 1.8, however it also brings many possible issues with it.
Since you're somewhat directly communicating with the client when sending certain packets, you must be really careful when creating those sent packets.
Usually if something goes wrong when using the spigot API, it would just create an error in the log and the code after would not be executed anymore. The player however wouldn't notice too much apart from some features not working or an error message popping up.
When working with packets, if one packet is configured incorrectly, the player will at least get kicked from the server, and in some cases, the recipient's entire game may crash!

NMS also contains a bunch of entity-related things such as PathfinderGoals and allows you to change them.
Therefore we are using NMS to change the vanilla's behaviour of entites and change them as we like!

 

STN Creatures

STN Creatures are really complex. Not only do they have custom set attributes such as health, defense, damage values etc, but they also have custom appearance, particles, sounds and some even have custom behaviour and attacks.

Some STN Creatures don't even look like enemies but instead more like a player (Winter Mining Creatures or Inquisitive Agarics for example).
Those are even more complex because their behaviour has to be copied onto a player model.
An Inquisitive Agaric is made of 3 main pieces:

  • The Nametag, an invisible ArmorStand without any hitbox.
    • Why an ArmorStand you may ask? ArmorStands are the only entity in 1.8 that when setting a custom name to them, they would still show it even when not directly looking at the entity.
  • The Player Model which has all the animations such as hitting, taking damage, burning, dying and so on. This Player Model doesn't  have any AI.
  • An invisible zombie which controls the Player Model. The zombie is modified with our custom PathfinderGoals.

As well as that, most entities are muted in this game. Meaning they don't play their default vanilla hit, death and idle sounds but instead received custom ones from us.

The main creature (the zombie in the case of the inquisitive agaric) then would receive all the mob tags such as which and how much skill exp to drop, which items you may drop from it and their drop chances, damage stats, defense stats, which bestiary to increase on kill and so on.

All of these tags are evaluated when hitting the creature or killing it.
Unfortunately though our current system was pretty bad for that:
In spigot certain events are getting triggered when certain things happen, such as hitting an entity.
So far we have used that one event and checked the hit entity, check if it has custom tags and then calculated loot, damage and everything else.
The class containing the event has well over 2,000 lines of code.

The Creature class itself only contains the custom attacks, setting up the creature and the appearance such as the nametag, custom armor, the player model and particle effects.

 

The new system

The new system is much better. Every creature now extends an overall Creature class which manages everything. It manages what happens when the creature is being hit, what happens when the creature dies, all the attributes and creature stats, behaviour and so on.

Let's say we want to add the Ice Guard creature to STN:
All we'd have to do now is creating an ICEGUARD object containing all the basic information (Health, Defense, Mob Level, Loot Table, etc.):

ICEGUARD("§bIce Guard", 500L, 100L, 200L, 0.15D, false, new AppearanceContainer(EntityType.SKELETON, true, "SkinData",
            "SkinData"),
            null, SkillType.MINING, 15L, 7, IceGuard.class, new SoundContainer(Sound.HURT_FLESH, 1f, 1.1f), new SoundContainer(Sound.GLASS, 1f, 1f), new SoundContainer(Sound.CAT_PURR, 1f, 1.7f), false, false, new ModifierContainer[]{new ModifierContainer(MobModifiers.FROZEN, null, false, true, false)}, true,
            new LootTableContainer[]{new LootTableContainer(Items.ICE, new int[]{2, 3, 4}, 1_000_000_000, false, null),
                    new LootTableContainer(Items.BRIGHT_CRYOCHUNK, new int[]{1, 2, 3}, 1_000_000_000, false, null),
                    new LootTableContainer(Items.BLOOD_FRAGMENT, new int[]{1}, Creature.getBloodFragmentOdds(7), true, ConsumableBuffs.MAGICALFISH)},
            new LootObjectContainer[]{new LootObjectContainer(Ender.class, 33, null, true)}, 240, 0);

And an IceGuard class which extends our Creature class:

class IceGuard extends Creature {

    @Creatures
    public IceGuard(Location location, boolean playerSpawned, boolean playerBound, Player player, boolean defaultBehaviour, boolean vector){
        super(CreatureTypes.ICEGUARD, location, EntityHeight.NPC, player, playerSpawned, playerBound, defaultBehaviour, vector, Bestiary.MLICEGUARD);
    }

    @Override
    public void kill(double damage, DamageTypes damageType, Player player) {
        super.kill(damage, damageType, player);
        // Add custom behaviour for when this creature is being killed
    }

    @Override
    public void setPathFinderGoals() {
        // Setting PathfinderGoals
    }

    @Override
    public void keepCreatureInBounds() {
        if(!isPlayerSpawned()){
            new BukkitRunnable(){
                public void run() {
                    // Keep Creature in bounds (Teleport them back to their spawnlocation when they leave their respective area)
                }
            }.runTaskTimer(Core.getPlugin(Core.class), 10, 10);
        }
    }
}

As you can see it is not too much code for a creature as complex as the Iceguard. The Iceguard would already be registered on the server and has the default hit behaviour and kill behaviour any other creature has.

If we want to customize it a little more we could just take some of the methods and override it with the needed code.

In the actual event listener (which contained the 2,000 lines of code prior to the new system) only the hit method of the creature is called as that contains all the behaviour, loot dropping and everything else we need to handle creature hits and kills.

This makes the code much more effective, easier to modify and makes it much easier for us to add new enemies to the game.
It also allows us to modify creatures when spawning them in. For example we're able to make them playerbound or even disable their custom attacks which couldn't be done that easily with the old system.

 

Upcoming Features

Due to the overall improvements of that system, we are able to implement some more features we wanted to add for a while but weren't possible due to the sheer complexity of the previous code.

- Lootshare
I have started a poll on the discord server yesterday asking you guys if you'd like to see an overall Lootshare system for most creatures of STN.

At the time of writing this devlog 9 of you voted for yes, so it's looking good!

Lootshare has already been a thing for sewer monsters but it was hardcoded and ONLY affected them. With the new system we are now able to easily implement that system to all the other creatures (apart from bosses)!

The lootshare system would reward the top players who helped in killing the creature with the same loot, however the dropchances would be much lower!

The lootshare system would not affect playerbound creatures such as mining creatures as other players are not supposed to hit it!

- Other Damage Causes
As you may have seen in one of the more recent sneak peeks on the discord server, I have added more damage causes to entites apart from just playerdamage, magicdamage and explosion damage! They now suffocate, take fall damage, drown and so on!
This allows us to add more custom items and enchants that apply poison to an enemy for example!

We are also able to add bows to the game now since entity damage is no longer 100% playerbound anymore and they may take damage from other souces as well!

 

Conclusion

The new system allows us to handle creatures in a much better and easy way. We are able to customize them a little bit better, modify existing ones and add new ones without many issues!

We don't have to copy-paste code anymore (Which you shouldn't do in general when coding in an OO programming language) and don't have to check code for 100% correctness as most code is only written once and automatically adopted to custom creatures and behaviour by the program.

STN Creatures aren't 100% done, bosses haven't been touched yet. Due to that the code I presented you may not be final and might be changed.

 

Systems that must still be reworked

This is more like a checklist with systems that will probably receive their own devlog once they're done.

  • Items
  • Achievements (abt 80%)
  • STN Creatures (abt 70%)
  • Inventories
  • NPCs
SurviveTheNight · 5 months ago · Last edited: 25 days ago