Topic category: User side tutorials
I WROTE THIS BEFORE VERSION 1.20.1
IN VERSIONS 1.20.1 AND ABOVE APPARENTLY THEYRE SYNCED AUTOMATICALLY SO YOU DON'T NEED TO READ THIS UNLESS UR USING AN OLD VERSION
Player Animator is a mod that allows your player to do pre-made animations and primarily shows them on client-side ONLY meaning that other players on a server cannot see them. While there are some animations that will play server-side (when entity swings main hand / takes damage) animations that trigger through any other method (when a player uses a keybind / potion effects triggers) will only be played on the player client that triggers the animation.
There is a way to get around this if you knew how to code in java, basically you have to allow the information that the client uses to play an animation to be send as a packet to a server which is then distributed across all clients, but I don't know how to code in java and the documentation makes my head spin. So, this guide takes that same principle but emulates it with mcreator generated code.
PLEASE READ THE WHOLE GUIDE. I TRIED TO MAKE IT AS ORGANIZED AS POSSIBLE BUT THERE MAY BE SOME IMPORTANT INFORMATION THAT IS SOMEWHAT HIDDEN IN AN EXPLANATION.
LOOK (WITH YOUR EYES) AT THIS REALLY BIG TEXT. IF YOU LEAVE A REPLY ASKING WHERE THE PICTURES ARE I AM NOT RESPONDING.
THE PICTURES ARE BROKEN, PLEASE REFER TO THIS GOOGLE DOC AND THE FIGURE NAMES FOR THE PICTURES: https://docs.google.com/document/d/1Zcca8-h6GRd7q0-0gLXcrlG_kktkFsJw_2Qp1SO58XU/edit?usp=sharing
THE BASIC PLAN
(ignore the text at the bottom, it was a side note that I guess I forgot to finish typing and just ended the sentence?)
Figure 1.1
Basically we are mimicking server-side animations by just giving the observing player information about what animation is being played and then having their client play that animation on their screen.
EXECUTION
(the part you probably care about)
SENDING THE "PACKET":
FROM NOW ON when you want a player to trigger an animation it should look like this. ("Ignore active animations" can be whatever you want, but I recommend false because setting it to true can cause some desync between what is being played and what people see)
Figure 1.2
This is important because its what sends the information to players that are observing you do the animation. The variables "animStorage" and "animPlayer" contain both the name of the animation that needs to be sent and the name of the player doing the animation respectively. The variable names themself are arbitrary, but for all purposes in this guide, these two variables will makeup our "packet" that we send to the other observing players. And also, the size of the square cube is arbitrary, its essentially just the render distance that the packet is sent, larger size mean more people will see it. For testing purposes I set it to 21 because it was a number I pulled out of thin air, but in the mod that I'm doing this for I was going to make it an option for players to make it larger or smaller (also with some basic trig you can make this range a circle instead of a cube). The word "blank" will appear pretty often and that's just because that's what i initialized the default state of the variable as. I recommend something that could not be a player name, but "blank" is just the first thing I thought of when I needed to represent that the stored information was blank.
PROCESSING THE "PACKET":
Figure 2.1
These are the procedures needed for rendering side of this idea (the parts necessary to process the data sent out from triggering an animation). The two that I have crossed out were for debugging purposes and are NOT necessary. Of course, the procedure names are arbitrary, but (and this should go without saying) all the animation names that are included should pertain to YOUR animation names in YOUR animation files.
The core of this processing is done by the "RenderRange" procedure:
Figure 2.2
This block of code will essentially scan around the observing player for players within their rendering radius (size of the square cube) and apply the packet, given by a player who triggers an animation, to that same player just on the client of the observing player. Basically, if player A does an animation, player B will not actually be able to see it. But, because of the "packet" that we send, when player A triggers an animation, player B gets the information of who is doing the animation and what animation is being played. Using this information from the "packet", player B's client can then, through this block of code, scan for any players that match the name of "player A" and then play the corresponding animation onto them from the perspective of player B. This is why I call it "pseudo server-side" communication.
The "ignore active animation" unfortunately needs to be false in this scenario. I have thought up a way to allow for both true and false animations to be played so that certain ones can cancel active animations, but I have not created a concrete method yet.
The "AnimReset" potion effect serves to reset the memory of the observing player once the animation has been played on their end. This is necessary because if the data was not cleared, it would keep looping the animation on the player that send the packet despite them not actually triggering anymore animations or "packet" sends on their end.
Figures 2.3 & 2.4
Again, "blank" is just an arbitrary string I came up with to represent the memory as empty. It can be anything u want it to be. Just make sure that if you replace it, you replace every instance of the word "blank" within the other necessary procedures as well as the initialization string of the variables "animStorage" and "animPlayer". Honestly, it shouldn't even be much of a problem unless you are the person who's minecraft username is actually just "blank".
Now, of course, having this block of code that will render the sent "packet" will do nothing if there is no trigger for it which is where the AnimRender potion effect comes in.
Figure 2.5
This potion effect is actually important because using a looping tick event like "on player tick update" will actually send some real packets to the server/client that mess with the effectiveness of this whole plan. A potion effect will process the procedures nested within it in a different way that acts much nicer for the purposes of this plan. (At least, that's what I think is happening, what you really need to know is that the potion effect is a lot less finnicky than the on player tick update trigger)
And finally, to apply this potion effect to the player so that they can render incoming "packets" containing the animations
Figure 2.6
OK SO LETS RECAP.
- Whenever a player triggers an animation, they will send a "packet" out to all observing players within a certain range that contains their name and the animation they're playing
- When an observing player receives this information, it is processed through a block of code that tells the observing player's client to play the necessary animation onto the player that triggered the information then clears its memory
- The block of code that processes the "packet" sent by the player needs to be run every tick to mitigate any desync between both the triggering players client and the observing players client. To do this, the block of code can't just be ran on every player tick update for some reason because it messes things up and causes a slew of problems. So, to get around that, the block of code is nested within a potion effect that will run it every tick. That same potion effect is then applied to all players every tick.
VIDEO: https://youtu.be/MmOBPTfksqQ?si=gNj_xmVVkWsK5wlP
The main monitor is the primary account, the triggering player, and the laptop is signed into an alt account (in spectator mode) observing my player do the animation
That's it, that's the whole guide. There is a reply below this one (by me) that shows how to make the server-side animation cancelable. The google doc also includes those pictures.
MarshMilo, thanks
Nerddogueto, on a server any animation that plays in the "when entity swings main hand" procedure of an item will play server-side no strings attached.
If you are proposing that putting a "swing main hand" block before a regular animation trigger in any procedure will trigger the aforementioned animation server-side then that is not the case.
The only way that I know of to get an animation to play server side (other than the guide that I wrote) is to put the animation trigger from the plugin ("if event/target entity is a player, play animation...") into the "when entity swings main hand" procedure of an item.
How did you do the item animation in the video? just wondering.
Marshmilo, Thank you very much! I understand now.
QTPieMuffet, I just made it real quick in blender. I used this blender rig -> emote_creator_bend_item.blend from KosmX's github (the guy who made the playeranimator mod)
Does this require the bendylib mod or no, @MarshMilo?
QTPieMuffet, it does not require the bendylib mod. Just dont use the bend bones and it'll work fine. The only mod you need is the playeranimator mod.
Most of the images on this page seem to have broken
ModsByDreamCritting, thanks for letting me know. I have updated the forum post.
All the images are broken can you fix so I can follow it, thanks
BabyMaxy2006 read the forum post.
MarshMilo , I very much appreciate this but i need help.
Hey, Ive followed every step and redid it all twice. Its still only working client side. Can you help me? Here is a collection of pics of everything. Link to the docs: https://docs.google.com/document/d/1T9xXdyqSxCn07eA7WlJG5wIS2LoIoLbENMKedO_NJZE/edit?usp=sharing
NekorsWolf, in the "TOnKeyPressed" procedure you mistakenly put the z coordinate of the cube at the x position of event target entity. Payment is not necessary LOL.
MarshMilo, The issue persists. No one is seeing the animations. Can you look over my doc again? I updated it. And if you see nothing wrong please consider making me an example workspace and/or letting me send mine to you. for free or pay bc i would really like this to work. https://docs.google.com/document/d/1T9xXdyqSxCn07eA7WlJG5wIS2LoIoLbENMKedO_NJZE/edit?usp=sharing