-
Notifications
You must be signed in to change notification settings - Fork 1
Examples
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.
Based on PacketEventsSK v1.1.2 with SkBee v3.22.1 on Paper v26.1.2 Created by Crebs huge shoutout!
Confetti using text displays
function confetti(p: player):
loop 1000 times:
confettiPiece({_p})
wait 1 tick
local function emptyText(loc: location):: fake entity:
set {_meta} to text 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 integer between 0 and 255, random integer between 0 and 255, random integer between 0 and 255)
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}
local function confettiPiece(p: player):
set {_loc} to {_p}'s location ~ (vector in direction of {_p})*vector(2.5, 2.25, 2.5)
set {_e} to emptyText({_loc})
set {_v} to vector(random number between -0.25 and 0.25, random number between 0.15 and 0.35, random number between -0.25 and 0.25)
set {_axis} to vector(random number between -1 and 1, random number between -1 and 1, random number between -1 and 1)
set {_angle} to random number between 0 and 360
set {_spin} to random number between 10 and 25
run 1 tick later repeating every 2 ticks:
add 1 to {_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 number between -0.01 and 0.01, 0, random number between -0.01 and 0.01)
set {_t} to vector(-0.03, 0.65, 0) + {_v}
set fake display translation of {_e} to {_t}
add {_spin} to {_angle}
set fake display left rotation of {_e} to axisAngle({_angle}, {_axis})Based on PacketEventsSK v1.1.0 with SkBee v3.22.1 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:
- server sends a fake sign with a line having a translatable component or keybind component (
clientbound block changepacket andclientbound block entity datapacket) - server forces the client to open the editor of the sign (
clientbound open sign editorpacket) - server forces the client to close the editor (
clientbound close windowpacket) - client closes the editor and as a response sends the "new content" (which is unchanged) to the server (
serverbound update signpacket received by server on line 57) - 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} to first element of {-keybindQueue::%{_uuid}%::*}
if {_keybind} is set:
check({_p}, {_keybind})
else:
delete {-keybindQueue::%{_uuid}%::*}
function check(p: player, keybind: string):
set {_pos} to vector of {_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: front
set {_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 async processed:
set {_p} to event-player
set {_uuid} to uuid of {_p}
if {-keybindQueue::%{_uuid}%::*} is set:
set {_firstIndex} to first element of indices of {-keybindQueue::%{_uuid}%::*}
set {_expected} to {-keybindQueue::%{_uuid}%::%{_firstIndex}%}
delete {-keybindQueue::%{_uuid}%::%{_firstIndex}%}
set {_updateSignPacket} to event-packet
set {_text} to {_updateSignPacket}.getTextLines()[0]
if {_text} is not {_expected}:
delete {-keybindQueue::%{_uuid}%::*}
wait tick # back on main thread
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 3 seconds
startKeybindChecks(player)Based on PacketEventsSK v1.1.1 with SkBee v3.22.1 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:
- user scrolls, the mc vanilla client sends
serverbound select bundle item - the server receives the packet and reads it's content (on line 34-36)
- we evaluate if the user scrolled up or down based on the data (line 68-87)
- we update the GUI accordingly
on load:
set {-baseBundle} to a bundle with item flags hide additional tooltip
add stone, stone, and stone to bundle contents of {-baseBundle}
command blocks:
trigger:
openBlocks(player)
function openBlocks(p: player, scroll: integer = 0):
set {_gui} to new chest inventory with 6 rows named "Blocks"
set {-prevPlayerScroll::%{_p}'s uuid%} to {_scroll}
set {_skipAmount} to {_scroll} * 9
set {_slot} to 0
loop blocks:
if any:
loop-iteration <= {_skipAmount}
type of loop-value is air
then:
continue
if {_slot} >= 54:
stop loop
set {_i} to {-baseBundle} named proper case "&f%loop-value%"
add stone, dirt and cobblestone to bundle contents of {_i}
set item model of {_i} to "%namespaced key of loop-value%"
set slot {_slot} of {_gui} to {_i}
add 1 to {_slot}
open {_gui} to {_p}
on serverbound select bundle item sync processed:
set {_index} to field selected item index of event-packet
set {_slotId} to field slot id of event-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 > 0
then:
clear {-prevScroll::%{_slotId}%}
openBlocks(player, {-prevPlayerScroll::%player's uuid%} - 1)
local function getScrollAction(prevIndex: integer, newIndex: integer, maxIndex: integer) :: string:
if {_newIndex} is -1:
return "DONE"
if {_prevIndex} is not set: # first scroll
if {_newIndex} is {_maxIndex} - 1:
return "UP"
else if {_newIndex} is 0:
return "DOWN"
if all:
{_prevIndex} is {_maxIndex} - 1
{_newIndex} is 0
then:
return "DOWN"
if all:
{_prevIndex} is 0
{_newIndex} is {_maxIndex} - 1
then:
return "UP"
if {_prevIndex} > {_newIndex}:
return "UP"
else:
return "DOWN"The guide was written by 3add and AmazinAxel