stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

10h 31m 30s logged

Leap VFX and new spells

The leap spell now has the simple VFX made last devlog attached. This is now possible thanks to the changes described below. It’s ugly, it usually just clips into the ground, but it’s better then nothing. I also added a new spell - ʔalɪˈvɑn wˈanga - wind shot. It shoots a wind projectile, for now - a wind charge, in the future - a custom one. You can see both in attached video. I also started working on a third spell - wind beam, but I wasn’t able to finish it this devlog.

Spell entites

The casting code rework is now done. After struggling for quite a lot of time, I managed to implement a SpellEntity, and rework how spells are built and registered. Let me tell you why it was hard.

Each spell is unique, with it’s own set of modifiers that translate to unique set of data that the spell needs to run. That data is needed both on the server, to run the logic, and on the client to display VFX. That meant I needed to find a way, to serialize the data for the client, and then have it figure out, what it just received. What came in clutch here is registry dispatch, descibed nicely on Fabric Docs.
Mojang built an entire serialization system called Codecs, which let’s you describe how a class can be serialized. Registry dispatch is a feature, where each you register each class to registry, along with such codec, and Minecraft can the use that to figure out how to deal with it. For that it uses a separate type, that I called SpellDefinition. It holds the codec, the brigadier spell node, the spell’s element, and also two new options - ticking and lifetimeTicks. The full casting pipeline now works like that:

  • Player says spell words
  • Those are detected by Sepple, send to server and accumulated.
  • When a new word is added the server uses Brigadier to check if the spell is finished, or timeout ran.
  • If so, the spell is cast - the brigadier command is executed.
  • Each spell implements the code executed here, and either runs it’s logic instantly, or creates a new instance of it’s own Spell subclass. Here any data the spell needs can be gathered, like the targets or parameters, and stored in the subclass. Then it is ran using it’s SpellCtx context class. SpellCtx holds details like the entity that casted the spell, a postion, a direction and some other details.
  • When a Spell is ran, a new SpellEntity holding it is spawned. The entity is synced to the client by Minecraft, along with the spell it is holding.
  • The entity calls the run function of the spell, and runClient on the client once. This is where a spell can implement it’s one-time logic, and pm client side - VFX. Additionally, if ticking was enabled in the definition, on each tick the tick function of the spell is called by the entity. This is where behavior that runs over time can be implemented. After the amount of ticks configured in the definition the spell entity despawns.

As you can see I have much more flexibility now, compare to the old system, where I only had a simple serverside callback for the logic.

/sephyr cast command

During development you sometimes need to cast one spell a lot, quickly. This happened when I was tweaking the leap spell VFX. The leap spell has the ɛvi (self) word in it, the detection of which often fails, because it is so short. It tired me, so I implemented a /sephyr cast <spell words> command, which can be used to run the spell. It’s creative mode only, because it ruins the point of the mod, but it is really helpful for testing. I managed to implement it quite neatly. The sephyr spells, similary to minecraft commands use the Brigadier command framework, but are registered separately. So I wrote a function, which walks the spell command tree, and registers analogous minecraft commands under /sephyr cast.

0
17

Comments 0

No comments yet. Be the first!