-
Notifications
You must be signed in to change notification settings - Fork 30
Qib System
Noxesium features a system for creating custom client-side interactable objects called the Qib System. This system is particularly useful for making server-side minigames such as Ace Race (from MC Championship).
The reason for needing this system is because of ping. If you model these interactable objects on the server you are going to experience a ~100ms activation delay on each of them for a large group of your players. Especially in movement games this delay will make the game feel far less fluid and far jankier. By implementing Noxesium's Qib System you can allow all players regardless of ping to have a fluid and fair experience.
This system centers around individual objects called Qibs (no good term exists, so we made our own). A qib is anything with a hitbox in the world that applies some effect to a player, often related to movement. Click Here to see a video showing a playthrough of a race map using the custom Qib System. It has a few different types of qibs:
- Speed Boosters which give the speed effect when walked over
- Launch Pads which send you flying in a direction when you jump on top of them
- Jump Pads which give you Jump Boost when on top of them
- Wind Tunnels which push you around
- Slow Fields which take away the speed effect and give you slowness
and quite a few more...
The Qib System is built in two parts, you must send the client a qib effect definition which describes how the client should act whenever it encounters any qib, and you must send interaction entities with special data to indicate where qibs are placed.
It is important to keep in mind that not all players on a server will be using Noxesium. If you want to rely on this system you will need to build a fallback for any player that does not have Noxesium installed. You may choose to model your server-side implementation after the way Noxesium is implemented on the client. Particularly its spatial collision tree might be of interest for doing performant qib collision detection.
To define the qib definition you can use the QIB_BEHAVIORS
server rule. This rule expects to find map of ids to JSON objects containing a QibDefinition object serialized with a specific GSON serializer. The QibDefinition is a JSON config file of sorts which describes which effects to apply to colliding players at which time. There are four types of interactions:
- On Enter which is triggered whenever a player collides with a specific qib entity for the first time. If
triggerEnterLeaveOnSwitch
isfalse
it will only trigger whenever a player collides with any qib of this definition type and will not re-trigger until the player leaves all qibs of this type. - On Leave which is triggered whenever a player stops colliding with a specific qib entity or type.
- While Inside is triggered every tick while a player is inside a specific qib entity.
- On Jump is triggered when a player presses jump while inside a specific qib entity. It should be noted that this is called instantly which mean your qib may interrupt the jump. Waiting for a few ticks before triggering your effect is recommended.
Each of these triggers needs a nullable QibEffect, if this effect is not null it is triggered. There are many different types of qib effects that can be nested to achieve a variety of effects. The following effects currently exist:
- Multiple which allows you to run multiple other effects in a row.
- Stay which triggers another effect only if the player remains inside the qib for a set amount of ticks. It can be tweaked to require staying inside any qib of the same type instead of just a specific instance.
- Wait waits a configurable amount of ticks before executing another given effect.
- Conditional executes another effect based on whether some basic conditions are correct. These conditions are related to checking the player's state such as if they are gliding, tridenting, on the ground, in water, etc.
- PlaySound plays a sound effect on the client player entity.
- GivePotionEffect gives a custom client-side potion effect to the local player. This only supports speed and jump boost at this time as these effects are implemented entirely custom. Normally the server is entirely in control of potion effects, so the client cannot decide itself to start experiencing an effect without causing major desyncs. For this reason these effects are fully custom and not communicated to the server.
- RemovePotionEffect removes a client potion effect. This cannot remove potion effects given by the server, only those given by other qibs.
- Move makes the player instantly move by a given offset. This is instant and respects block collisions.
- AddVelocity adds additional velocity to the player's current velocity.
- SetVelocity replaces the player's current velocity with a new value.
- SetVelocityYawPitch replaces the player's current velocity with a new value, but determines the direction vector based on a yaw, pitch and strength value. The yaw and pitch can both be made relative to the current yaw/pitch of the player, allowing you to make jump pads that go in the direction the player is facing instead of a pre-determined one.
Additional documentation can be found in the code where these effects are defined. You can also inspect the way they are implemented on the client. Furthermore, whenever the client triggers a qib effect it informs the server so it can do whatever it wishes.
After you have defined which types of qibs exist you must create specific entities to trigger these effects. At this time, entities cannot have their own qib definitions directly and all qibs definitions must be registered as uniquely named types.
Qib entities are made using Interaction entities, these can be freely placed and resized making them ideal for creating arbitrary hitboxes. However, in vanilla interaction enities have the same width on both the x- and z-axis. For this purpose Noxesium introduces a custom entity rule called QIB_WIDTH_Z
which can be used to make interaction entities have any size.
You can use the QIB_BEHAVIOR
entity rule to set the definition/type a specific qib uses. Any interaction entity with a qib behavior will be ignored by any Noxesium client. It will not function like an actual interaction entity.
You can find examples on how to configure entity rules in the provided Paper implementation.
It is also recommended that you make the interaction entities invisible which hides them from F3+B. This prevents players from easily seeing where all hitboxes are.
A debug viewer is built into Noxesium which you can use to debug your usage of qib entities. It can be enabled in the F3+V menu under Debug Qib System. It will show all interaction entities as highlighted and when F3+B is toggled it instead shows the state of each qib, showing you whether it has been properly recognised.
There is a system for using custom improved trident physics which can be used in tandem with the Qib System. This requires making various server-side modifications as both the client and server need to act differently. This system has to be enabled using the ENABLE_SMOOTHER_CLIENT_TRIDENT
client rule. If you use the provided Noxesium server-side API implementation in the paper module of this repository, the server will automatically ensure that the client is running a compatible version of Noxesium that can use the smoother client trident.
The smoother client trident exists because the vanilla trident has a few issues when a player has higher ping, this is caused by a few key issues in Mojang's implementation:
- The sound effect of a trident throw is played on the server-side.
- The entity metadata indicating a player is in the tridenting pose is set by the server. Since the pose controls the client camera this means the client's camera height does not update until the trident usage has been sent to the server and back.
- Using the trident does not send a packet to the server, instead the activation of the trident is inferred based on how long the player has held it down for. This can cause only the client or only the server to trigger a riptide causing various visual glitches.
For these reasons there is a benefit in using this smoother client trident which strips out all server-side handling of the trident and makes the client do everything. For this to work a few edits need to be made on the server:
- Run the provided server-side Paperweight patches for Paper-API and Paper-Server. These entirely disable the trident behavior for anyone using the client-side trident.
- It is recommended to implement some changes to vanilla to prevent sending an entity's POSE data back to the client itself. This is because the pose of the client player is normally updated entirely client-side, but the server unnecessarily sends this information again. Not implementing this should not prevent the trident changes from working, but it might interfere.
- You must implement some code to trigger the riptide effect on the server whenever Noxesium sends a SERVER_RIPTIDE packet. Here is an example implementation in Kotlin using some custom extension functions that simply copies relevant parts of the vanilla code:
// Listen to the client using the riptide to trigger it on the server
NoxesiumPackets.SERVER_RIPTIDE.addListener(this) { packet, player ->
val stack = player.inventory.getItem(packet.slot)?.nms ?: return@addListener
val holder = EnchantmentHelper.pickHighestLevel(stack, EnchantmentEffectComponents.TRIDENT_SOUND)
.orElse(SoundEvents.TRIDENT_THROW)
CraftEventFactory.callPlayerRiptideEvent(player.nms, stack, 0f, 0f, 0f)
player.nms.startAutoSpinAttack(20, 8.0F, stack)
player.world.nms.playSound(
player.nms,
player.nms,
holder.value() as SoundEvent,
SoundSource.PLAYERS,
1.0f,
1.0f,
)
}
The last line specifically plays the riptide noise to other players and not the player that is riptiding themselves.
- Finally your resource pack should include a sound effect with id
noxesium:trident.ready_indicator
that plays whenever the trident is ready to throw.
The client-side trident comes with the following features:
- Everything happens instantly on the client, the sound plays and the pose updates instantly.
- Adds an indicator sound whenever you can release the trident.
- Changes the way the held item is rendered to reduce flickering when rapidly using the trident.
- Adds coyote time to the trident. This allows it to be thrown for a few ticks after a player has left the water. This makes the trident feel much smoother to use as you commonly leave the water when swimming on the surface. You can customise how many ticks of coyote time are given using the
RIPTIDE_COYOTE_TIME
server-rule. Setting this rule to 0 will disable this feature. You can debug the feature using the Debug Qib System toggle which will show in the top left whenever coyote time is taking effect.
If you've made it this far in this article, feel free to join my Discord where you can ask for help in the #noxesium channel.