Skip to content
3add edited this page May 23, 2026 · 30 revisions

This page lists examples of things you can do with PacketEventsSK. This page is made for you to understand the syntax and ideas of package management, do not just copy paste the listed content.

Welcome

Based on PacketEventsSK v1.1.3 with SkBee v3.23.0 on Paper v26.1.2

on join:
set {_p} to player
set {_meta} to a new fake text display meta:
display billboard: center
display content: "<rainbow>WELCOME %{_p}%"set {_display} to a new fake text display entity:
location: location 2 blocks infront of player
viewers: player
meta: {_meta}
set {_interactionMeta} to a new fake interaction meta:
interaction height: 1
interaction width: 2set {_interactable} to a new fake interaction entity:
location: location 2 blocks infront of player
viewers: player
meta: {_interactionMeta}
set {-interactables::%{_p}'s uuid%} to fake entity idof {_interactable}
wait 5seconds
kill fake entities {_display} and {_interactable}
clear {-interactables::%player's uuid%}
on serverbound interact entity:
set {_id} to packet field entity idofevent-packet
set {_hand} to packet field hand ofevent-packet
set {_sneaking} to packet field sneaking state ofevent-packet
if all:
{_id} is {-interactables::%player's uuid%}
# this packet is sent for each hand when just regular clicking# "main hand" is parsed as equipment slot if literal so we parse from text
{_hand} is"main hand" parsed as interaction hand
{_sneaking} isfalsethen:
send "<rainbow>welcome player!"

Reduced Debug Toggle

Based on PacketEventsSK v1.1.4 with SkBee v3.23.0 on Paper v26.1.2

This examples can be used to hide things such as coordinates from players' f3 menus. It's a rather simple example. Full list can be found here: Debug Screen info lines (more info on entity status can be found here: Entity Statuses)

# hides certain things (including XYZ) from the f3 menu
command toggleDebug:
trigger:
set {_entityId} to protocol idof player
if {-debugMode::%player's uuid%} istrue:
set {-debugMode::%player's uuid%} tofalseset {_status} to23else:
set {-debugMode::%player's uuid%} totrueset {_status} to22set {_packet} to a new clientbound entity status packet:
entity id: {_entityId}
status: {_status}
send packet {_packet} to player

Confetti

Based on PacketEventsSK v1.1.3 with SkBee v3.23.0 on Paper v26.1.2

Created by Crebs huge shoutout!

Confetti using text displays

function confetti(p: player):
loop 1000times:
confettiPiece({_p})
wait 1 tick
localfunctionemptyText(loc: location):: fakeentity:
set {_meta} totext display meta data:
display content: ""
display text shadowed state: true
display billboard: center
display scale: vector(1.2,1.2,1.2)
display translation: vector(-0.03,0.65,0)
display background color: rgb(random integerbetween0and255, random integerbetween0and255, random integerbetween0and255)
display view range: 1
display transform interpolation duration: 2 ticks
display interpolation delay: 0 ticks
return a new fake text display entity:
viewers: all players
location: {_loc} ~ vector(0,0.5,0)
meta: {_meta}
localfunctionconfettiPiece(p: player):
set {_loc} to {_p}'s location ~ (vectorin direction of {_p})*vector(2.5, 2.25, 2.5)
set {_e} to emptyText({_loc})
set {_v} tovector(random numberbetween-0.25and0.25, random numberbetween0.15and0.35, random numberbetween-0.25and0.25)
set {_axis} tovector(random numberbetween-1and1, random numberbetween-1and1, random numberbetween-1and1)
set {_angle} torandom numberbetween0and360set {_spin} torandom numberbetween10and25run1 tick later repeating every2 ticks:
add 1to {_c}
if {_c} >=70:
kill fake entity {_e}
stop
set {_v} to ({_v} *vector(0.93, 1, 0.93)) -vector(0, 0.05, 0) +vector(random numberbetween-0.01and0.01, 0, random numberbetween-0.01and0.01)
set {_t} tovector(-0.03, 0.65, 0) + {_v}
set meta display translation of {_e} to {_t}
add {_spin} to {_angle}
set meta display left rotation of {_e} to axisAngle({_angle}, {_axis})

Sign Exploit

Based on PacketEventsSK v1.1.3 with SkBee v3.23.0 on Paper v26.1.2

This example makes use of a sign exploit described in MC-265322 and on wurst wiki. It can be used to see which mods are or aren't installed on a connected player. (and is thus very powerful for anti cheating purposes)

Basically the way it works:

  1. server sends a fake sign with a line having a translatable component or keybind component (clientbound block change packet and clientbound block entity data packet)
  2. server forces the client to open the editor of the sign (clientbound open sign editor packet)
  3. server forces the client to close the editor (clientbound close window packet)
  4. client closes the editor and as a response sends the "new content" (which is unchanged) to the server (serverbound update sign packet received by server on line 57)
  5. server reads the new content: if it parsed the translatable/keybind component it has the keybind set and thus has the mod otherwise not
on load:
delete {-blackListedKeybinds::*}
add "key.freecam.toggle"to {-blackListedKeybinds::*}
add "key.freecam.playerControl"to {-blackListedKeybinds::*}
add "key.freecam.tripodReset"to {-blackListedKeybinds::*}
add "key.freecam.configGui"to {-blackListedKeybinds::*}
function createSignNBT(bind: string) :: nbt compound:
set {_nbtString} to"{front_text:{messages:[{""keybind"":""%{_bind}%""},{""text"":""""},{""text"":""""},{""text"":""""}]}}"return nbt compound from {_nbtString}
function startKeybindChecks(p: player):
set {_uuid} to uuid of {_p}
delete {-keybindQueue::%{_uuid}%::*}
loop {-blackListedKeybinds::*}:
add loop-value to {-keybindQueue::%{_uuid}%::*}
checkNextKeybind({_p})
function checkNextKeybind(p: player):
set {_uuid} to uuid of {_p}
set {_keybind} tofirst element of {-keybindQueue::%{_uuid}%::*}
if {_keybind} isset:
check({_p}, {_keybind})
else:
delete {-keybindQueue::%{_uuid}%::*}
function check(p: player, keybind: string):
set {_pos} tovectorof {_p}'s location
set {_blockPacket} to a new clientbound block change packet:
block position: {_pos}
block state: oak sign[]
set {_setTextPacket} to a new clientbound block entity data packet:
block position: {_pos}
block entity type: sign block entity type
nbt compound: createSignNBT({_keybind})
set {_signPacket} to clientbound open sign editor packet:
block position: {_pos}
sign side: frontset {_closeWindowPacket} to a clientbound close window packet
set {_revertBlockPacket} to new clientbound block change packet:
block position: {_pos}
block state: air[]
# Sends the packets (order sensitive)
send packet {_blockPacket}, {_setTextPacket}, {_signPacket}, {_closeWindowPacket} and {_revertBlockPacket} to {_p} on serverbound update sign packet sync processed:
set {_p} toevent-player
set {_uuid} to uuid of {_p}
if {-keybindQueue::%{_uuid}%::*} isset:
set {_firstIndex} tofirst element of indices of {-keybindQueue::%{_uuid}%::*}
set {_expected} to {-keybindQueue::%{_uuid}%::%{_firstIndex}%}
delete {-keybindQueue::%{_uuid}%::%{_firstIndex}%}
set {_updateSignPacket} toevent-packet
set {_text} tofirst element of packet sign lines ofevent-packet
if {_text} is not {_expected}:
delete {-keybindQueue::%{_uuid}%::*}
kick {_p} due to"Unsupported client modification detected!"else:
send "%{_p}% passed keybind check for: %{_expected}%"to console
wait 1 tick
if {_p} is online:
checkNextKeybind({_p})
on join:
wait 3seconds
startKeybindChecks(player)

Scrollable GUI

Based on PacketEventsSK v1.1.3 with SkBee v3.23.0 on Paper v26.1.2

This example makes use of another unintended feature of the minecraft protocol that allows for a scrollable GUI (where the content scrolls with you) There are multiple ways of doing this but one of the ways is intercepting a serverbound select bundle item packet and based of it's data determining in which direction the client scrolled. Works like this:

  1. user scrolls, the mc vanilla client sends serverbound select bundle item
  2. the server receives the packet and reads it's content (on line 34-36)
  3. we evaluate if the user scrolled up or down based on the data (line 68-87)
  4. we update the GUI accordingly
on load:
set {-baseBundle} to a bundle withitem flags hide additional tooltip
add stone, stone, and stone to bundle contentsof {-baseBundle}
command blocks:
trigger:
openBlocks(player)
function openBlocks(p: player, scroll: integer=0):
set {_gui} to new chest inventory with6 rows named"Blocks"set {-prevPlayerScroll::%{_p}'s uuid%} to {_scroll}
set {_skipAmount} to {_scroll} *9set {_slot} to0
loop blocks:
if any:
loop-iteration <= {_skipAmount}
type of loop-value is air
then:
continueif {_slot} >=54:
stop loop
set {_i} to {-baseBundle} named proper case "&f%loop-value%"
add stone, dirt and cobblestone to bundle contentsof {_i}
setitem model of {_i} to"%namespaced key of loop-value%"set slot {_slot} of {_gui} to {_i}
add 1to {_slot}
open {_gui} to {_p}
on serverbound select bundle item sync processed:
set {_index} to packet selected itemindexofevent-packet
set {_slotId} to packet slot idofevent-packet
set {_action} to getScrollAction({-prevScroll::%{_slotId}%}, {_index}, 3)
if {_action} is"DONE":
clear {-prevScroll::%{_slotId}%}
else:
set {-prevScroll::%{_slotId}%} to {_index}
if {_action} is"UP":
clear {-prevScroll::%{_slotId}%}
openBlocks(player, {-prevPlayerScroll::%player's uuid%} +1)
else if all:
{_action} is"DOWN"
{-prevPlayerScroll::%player's uuid%} -1>0then:
clear {-prevScroll::%{_slotId}%}
openBlocks(player, {-prevPlayerScroll::%player's uuid%} -1)
localfunctiongetScrollAction(prevIndex: integer, newIndex: integer, maxIndex: integer) :: string:
if {_newIndex} is-1:
return"DONE"if {_prevIndex} is notset: # first scrollif {_newIndex} is {_maxIndex} -1:
return"UP"else if {_newIndex} is0:
return"DOWN"if all:
{_prevIndex} is {_maxIndex} -1
{_newIndex} is0then:
return"DOWN"if all:
{_prevIndex} is0
{_newIndex} is {_maxIndex} -1then:
return"UP"if {_prevIndex} > {_newIndex}:
return"UP"else:
return"DOWN"

Clone this wiki locally