Most of this is going to be packet stuff. ALL PACKET STUFF IS ONLY TESTED ON 1.8.8
Type ID Function
New "UUID"
Client Side Mobs
Client Side Objects
Client side blocks
Titles
Set Arrows in Body
Get Specific Spawner Item
Sign GUI
Teleport with passengers/vehicles
Prettify JSON
Crafting Utils
Resource Pack Tools
Brewing shit
Recipe Grabber
Cancel Block Drops (potentially unsafe)
Rotate a player's pitch/yaw without teleportation
NPCs
Cancelled. See below.
Type ID Function
In packets, particularly when dealing with spawn packets you may need a type id to identify what mob you want to spawn. There isn't an easy way to do this with just MundoSK so I just decided to make it manually. It isn't really useful for much on its own.
code_language.skript:
function typeId(entity: string) :: object: #I have to use string here because the entitytype type is... weird, and not all of them match up with wiki.vg
switch {_entity}: #everything is here except things marked as blue on wiki.vg
case "Item":
return 2
case "AreaEffectCloud":
return 3
case "ElderGuardian":
return 4
case "WitherSkeleton":
return 5
case "Stray":
return 6
case "ThrownEgg":
return 62
case "LeashKnot":
return 77
case "Arrow":
return 60
case "Snowball":
return 61
case "Fireball":
return 63
case "SmallFireball":
return 64
case "ThrownEnderpearl":
return 14
case "EyeOfEnderSignal":
return 72
case "ThrownPotion":
return 73
case "ThrownExpBottle":
return 75
case "ItemFrame":
return 71
case "WitherSkull":
return 66
case "PrimedTnt":
return 50
case "FallingSand":
return 70
case "FireworksRocketEntity":
return 76
case "Husk":
return 23
case "SpectralArrow":
return 91
case "ShulkerBullet":
return 67
case "DragonFireball":
return 93
case "ZombieVillager":
return 27
case "SkeletonHorse":
return 28
case "ZombieHorse":
return 29
case "ArmorStand":
return 30 #careful, this will crash your game if you don't send it right
case "Donkey":
return 31
case "Mule":
return 32
case "EvocationFangs":
return 79
case "EvocationIllager":
return 34
case "Vex":
return 35
case "VindicationIllager":
return 36
case "IllusionIllager":
return 37
case "MinecartCommandBlock":
return 10
case "Boat":
return 1
case "MinecartRideable":
return 10
case "MinecartChest":
return 10
case "MinecartTNT":
return 10
case "MinecartHopper":
return 10
case "MinecartSpawner":
return 10
case "Creeper":
return 50
case "Skeleton":
return 51
case "Spider":
return 52
case "Giant":
return 53
case "Zombie":
return 54
case "Slime":
return 55
case "Ghast":
return 56
case "PigZombie":
return 57
case "Enderman":
return 58
case "CaveSpider":
return 59
case "Silverfish":
return 60
case "Blaze":
return 61
case "LavaSlime":
return 62
case "EnderDragon":
return 63
case "WitherBoss":
return 64
case "Bat":
return 65
case "Witch":
return 66
case "Endermite":
return 67
case "Guardian":
return 68
case "Shulker":
return 69
case "Pig":
return 90
case "Sheep":
return 91
case "Cow":
return 92
case "Chicken":
return 93
case "Squid":
return 94
case "Wolf":
return 95
case "MushroomCow":
return 96
case "SnowMan":
return 97
case "Ozelot":
return 98
case "VillagerGolem":
return 99
case "Horse":
return 100
case "EntityHorse":
return 100
case "Rabbit":
return 101
case "PolarBear":
return 102
case "Llama":
return 103
case "LlamaSpit":
return 68
case "Parrot":
return 105
case "Villager":
return 120
case "EnderCrystal":
return 51
return false
The function is used like
. It returns either the type id of the given entity or false if the entity isn't found.
code_language.skript:
set {_id} to typeId("chicken")
MundoSK (pref. the latest beta)
New "UUID"
This "UUID" isn't really unique, and it shouldn't be used as such. It's sole purpose is for use in packets that need a uuid, and this does the job
code_language.skript:
function newUUID(i: int = 0) :: string:
return "%a random integer between 10000000 and 99999999%-%a random integer between 1000 and 9999%-%a random integer between 1000 and 9999%-%a random integer between 1000 and 9999%-%a random integer between 100000000000 and 999999999999%"
Used like
and it returns a string in the template of a UUID
code_language.skript:
newUUID()
MundoSK (pref. the latest beta)
Client Side Mobs
Lets you spawn fake mobs for specific players only.
code_language.skript:
function spawnClientMob(entity: string, location: location, viewers: players, entityid: int = 69420) :: object:
if typeId({_entity}) is false: #if the given entity isn't in the typeId() function, stop the function by returning false so that the calling code can detect there was an issue if it chooses to
return false
set {_packet} to new play_server_spawn_entity_living packet
if {_entityid} is 69420: #if a custom id wasn't specified
set int pnum 0 of {_packet} to a random integer from 50000 to 100000 #set the entity id to a number that won't realitically ever cause problems
else: #if a custom id WAS specified
set int pnum 0 of {_packet} to {_entityid} #set the entity id to the given id
set int pnum 1 of {_packet} to "%typeId({_entity})%" parsed as a number #get the type id used to identify the given mob in packets, has to be parsed as a number because the function returns object
#set the coordinates
set int pnum 2 of {_packet} to {_location}'s x-loc * 32
set int pnum 3 of {_packet} to {_location}'s y-loc * 32
set int pnum 4 of {_packet} to {_location}'s z-loc * 32
#set the pitch/yaw
loop 5 and 6:
set int pnum loop-value of {_packet} to 0
#set the velocity
loop 7, 8 and 9 :
set int pnum loop-value of {_packet} to 0
#send all the players that should see the mob the packet
loop {_viewers::*}:
send loop-value packet {_packet}
return "%int pnum 0 of {_packet}%" parsed as an int #if we've gotten this far, return the entity id in case the calling code needs to use it to manipulate the spawned mob
Usage is
and the function returns either false if the entity wasn't found or the entity id of the newly spawned mob in the event you would like to use it for something
code_language.skript:
spawnClientMob("chicken", player's location, player)
spawnClientMob("entity", location, viewers)
MundoSK (pref. the latest beta)
Client Side Objects
Lets you spawn fake objects for specific players only.
code_language.skript:
function spawnClientObject(object: string, location: location, viewers: players, data: int = 1, entityid: int = 69420) :: object:
if typeId({_object}) is false: #if the given object isn't in the typeId() function, stop the function by returning false so that the calling code can detect there was an issue if it chooses to
return false
set {_packet} to new play_server_spawn_entity packet
if {_entityid} is 69420: #if a custom id wasn't specified
set int pnum 0 of {_packet} to a random integer from 50000 to 100000 #set the entity id to a number that won't realistically ever cause problems
else: #if a custom id WAS specified
set int pnum 0 of {_packet} to {_entityid} #set the entity id to the given id
set int pnum 9 of {_packet} to "%typeId({_object})%" parsed as a number #get the type id used to identify the given object in packets, has to be parsed as a number because the function returns object
#set the coordinates
set int pnum 1 of {_packet} to {_location}'s x-loc * 32
set int pnum 2 of {_packet} to {_location}'s y-loc * 32
set int pnum 3 of {_packet} to {_location}'s z-loc * 32
#set the pitch/yaw
loop 7 and 8:
set int pnum loop-value of {_packet} to 0
#set the data
set int pnum 10 of {_packet} to {_data}
#send all the players that should see the mob the packet
loop {_viewers::*}:
send loop-value packet {_packet}
return "%int pnum 0 of {_packet}%" parsed as an int #if we've gotten this far, return the entity id in case the calling code needs to use it to manipulate the spawned object
Usage is
and the function returns either false if the object wasn't found or the entity id of the newly spawned object in the event you would like to use it for something
code_language.skript:
spawnClientObject("arrow", player's location, player)
spawnClientObject("object", location, viewers)
MundoSK (pref. the latest beta)
Client side blocks
Make a block look like something it isn't for specific players
code_language.skript:
function clientBlock(location: location, type: item, viewers: players):
set {_packet} to new play_server_block_change packet
set location pinfo 0 of {_packet} to {_location}
set "BlockData" pinfo 0 of {_packet} to {_type} # as seen on packetwrapper, this uses the blockdata pinfo
loop {_viewers::*}: #show peeps the new block
send loop-value packet {_packet}
This function is used like
code_language.skript:
clientBlock(player's location, diamond ore, all players)
MundoSK, pref the latest beta
Titles
Lets you send titles and subtitles to players, with a fadein/fadeout and stay time
code_language.skript:
function title(players: players, title: string, subtitle: string, stay: int, fadein: int, fadeout: int):
set {_reset} to new play_server_title packet
set "TitleAction" penum 0 of {_reset} to "RESET"
loop "" and "SUB":
set {_%loop-value%titlepacket} to new play_server_title packet
set "chatcomponent" pjson 0 of {_%loop-value%titlepacket} to packetJson({_%loop-value%title})
set "TitleAction" penum 0 of {_%loop-value%titlepacket} to "%loop-value%TITLE"
set {_timepacket} to new play_server_title packet
set "TitleAction" penum 0 of {_timepacket} to "TIMES"
set int pnum 0 of {_timepacket} to {_fadein}
set int pnum 1 of {_timepacket} to {_stay}
set int pnum 2 of {_timepacket} to {_fadeout}
loop {_players::*}:
send loop-value packet {_reset}
send loop-value packet {_timepacket}
send loop-value packet {_subtitlepacket}
send loop-value packet {_titlepacket}
code_language.skript:
title(all players, "title", "subtitle", 50, 4, 3)
MundoSK (pref. latest beta), SnowPyon's packetJson function
Set Arrows in Body
code_language.skript:
setArrows(all players, 127)
code_language.skript:
on script load:
import "java.lang.Byte"
function setArrows(number: number, player: player) :: boolean:
if {_number} is less than or equal to {Byte}.MAX_VALUE!:
if {_number} is greater than or equal to {Byte}.MIN_VALUE!:
set {_l::*} to 9 and new {Byte}("%{_number}%")
{_player}.getHandle().getDataWatcher().watch({_l::*});
return true
return false
code_language.skript:
on script load:
import "org.bukkit.Bukkit"
set {_nms::*} to ...{Bukkit}.getServer().getClass().getPackage().getName().replace("." and ",").split(",")
set {_nms} to "net.minecraft.server.%{_nms::4}%"
import "%{_nms}%.DataWatcherRegistry"
import "%{_nms}%.DataWatcherObject"
import "%{_nms}%.DataWatcher"
import "java.lang.Byte"
import "java.lang.Float"
import "java.lang.Integer"
function setArrows(players: players, number: number) :: boolean:
if {_number} is less than or equal to {Byte}.MAX_VALUE!:
if {_number} is greater than or equal to {Byte}.MIN_VALUE!:
set {_args::*} to new {Float}("10") and {DataWatcherRegistry}.b!
set {_args::*} to new {DataWatcherObject}({_args::*}) and new {Byte}("%{_number}%")
loop {_players::*}:
try loop-value.getHandle().getDataWatcher().set({_args::*});
return true
return false
skript-mirror
Get Specific Spawner Item
code_language.skript:
give spawner("creeper") to player
code_language.skript:
on script load:
import "org.bukkit.inventory.meta.BlockStateMeta"
import "org.bukkit.entity.EntityType"
import "org.bukkit.block.CreatureSpawner"
import "org.bukkit.inventory.ItemStack"
function spawner(entity: string) :: item:
set {_enum} to try {EntityType}.valueOf({_entity}.toUpperCase())
set {_spawner} to mob spawner
set {_spawner} to {_spawner}.getRandom()
set {_blockStateMeta} to {_spawner}.getItemMeta() as {BlockStateMeta}
set {_creatureSpawner} to {_blockStateMeta}.getBlockState() as {CreatureSpawner}
{_creatureSpawner}.setSpawnedType({_enum});
{_blockStateMeta}.setBlockState({_creatureSpawner});
set {_spawner} to {_spawner} as {ItemStack}
{_spawner}.setItemMeta({_blockStateMeta});
return {_spawner}
skript-mirror
Sign GUI
code_language.skript:
signGUI(player, "Search Below", "", "^^^^", "Search Above")
code_language.skript:
on skript load:
delete {signguis::*}
on script load:
import "org.bukkit.Material"
function clientBlock(location: location, type: object, viewers: players, data: int = 0):
set {_material} to check [{_type} is a text] ? try {Material}.valueOf({_type}.toUpperCase()) : ({_type}.getRandom() ? {_type}).getType()
set {_args::*} to {_location}, {_material} and {_data}
loop {_viewers::*}:
try loop-value.sendBlockChange({_args::*});
function clientSign(players: players, location: location, 1: string = "", 2: string = "", 3: string = "", 4: string = ""):
set {_args::*} to {_location}
add [({_1}, {_2}, {_3} and {_4}) as string] to {_args::*}
loop {_players::*}:
try loop-value.sendSignChange({_args::*});
function getLines(packet: packet) :: strings:
loop ...{_packet}.getHandle().b():
add "%loop-value.getText()%" to {_lines::*}
return {_lines::*}
function signGUI(player: player, 1: string = "", 2: string = "", 3: string = "", 4: string = ""):
set {_x} to x-loc of {_player}
set {_z} to z-loc of {_player}
set {_y} to y-loc of {_player}
set {_world} to world of {_player}
set {_packet} to new play_server_open_sign_editor packet
set {_location} to location(round({_x}), 0, round({_z}), {_world})
set location pinfo 0 of {_packet} to {_location}
if "%{_1}%%{_2}%%{_3}%%{_4}%" is not "":
clientBlock({_location}, "sign_post", {_player})
clientSign({_player}, {_location}, {_1}, {_2}, {_3}, {_4})
set {_reset} to true
send {_player} packet {_packet}
set {_uuid} to uuid of {_player}
set {signguis::%{_uuid}%} to true
if {_reset} is set:
set {_type} to type of block at {_location}
clientBlock({_location}, {_type}, {_player})
on packet event play_client_update_sign:
if {signguis::%player's uuid%} is set:
delete {signguis::%player's uuid%}
sync:
call custom event "sign gui done" to details (event-player, event-packet, world of {_location} and {_location}) args getLines(event-packet)
skript-mirror, MundoSK (pref. latest beta), skquery
code_language.skript:
command /opensign:
trigger:
signGUI(player, "Hello there!", "How are you,", "%player%?")
evt "sign gui done":
set {_lines::*} to custom event's args
broadcast "%event-player% input %join nl and {_lines::*} with nl%"
broadcast "%event-location%"
broadcast "%event-world%"
broadcast "%packettype of event-packet%"
Teleport with passengers/vehicles
code_language.skript:
teleport(player, target block)
code_language.skript:
function teleport(e: entity, l: location):
set {_v} to {_e}'s vehicle
set {_p} to {_e}'s passenger
make {_e}'s passenger dismount
make {_e} dismount
teleport {_e} to {_l}
teleport({_v}, {_l})
make {_e} ride {_v}
teleport({_p}, {_l})
make {_p} ride {_e}
Vanilla skript
Prettify JSON
code_language.skript:
prettifyJson("{""whatever"":""something"",""test"":{""stuff"":true}}")
code_language.skript:
on script load:
import "com.google.gson.GsonBuilder"
import "com.google.gson.JsonParser"
set {prettify::json::parser} to new {JsonParser}()
set {prettify::json::builder} to new {GsonBuilder}()
set {prettify::json::builder} to {prettify::json::builder}.setPrettyPrinting().create()
function prettifyJson(json: string) :: string:
set {_builder} to {prettify::json::builder}
set {_parsed} to try {prettify::json::parser}.parse({_json})
if {_parsed} is not set:
return {_json}
set {_object} to {_parsed}.getAsJsonObject()
set {_pretty} to {prettify::json::builder}.toJson({_object})
return {_pretty}
skript-mirror
Crafting Utils
code_language.skript:
getCraftingResult(event) # in a craft event
setCraftingResult(event, dirt) # in a craft event
code_language.skript:
on script load:
import "org.bukkit.Bukkit"
set {_rev::*} to ...{Bukkit}.getServer().getClass().getPackage().getName().replace("." and ",").split(",")
import "org.bukkit.craftbukkit.%{_rev::4}%.inventory.CraftItemStack"
import "net.minecraft.server.%{_rev::4}%.ItemStack" as {NMSItemStack}
function getCraftingResult(event: event) :: item:
set {_item} to first element out of (...{_event}.getInventory().resultInventory!.items!)
return {CraftItemStack}.asBukkitCopy({_item})
function setCraftingResult(event: event, item: item):
set {_event}.getInventory().resultInventory!.items! to [{CraftItemStack}.asNMSCopy({_item}) as {NMSItemStack}]
skript-mirror
code_language.skript:
on craft:
if getCraftingResult(event) is tnt:
setCraftingResult(event, 64 tnt)
Resource Pack Tools
code_language.skript:
sendPack(all players, "name", "url", "hash")
code_language.skript:
on skript unload:
delete {packs::*}
function getHash(id: number) :: string:
return {packs::info::%{_id}%::hash}
function getUrl(id: number) :: string:
return {packs::info::%{_id}%::url}
function getName(id: number) :: string:
return {packs::info::%{_id}%::name}
function sendPack(players: players, name: string, url: string, hash: string):
set {_packet} to new play_server_resource_pack_send packet
set string pinfo 0 of {_packet} to {_url}
set string pinfo 1 of {_packet} to {_hash}
set {_id} to size of {packs::info::*}
set {packs::info::%{_id}%} to true
loop "hash", "url" and "name":
set {packs::info::%{_id}%::%loop-value%} to {_%loop-value%}
loop {_players::*}:
call custom event "resource pack sent" to details loop-value
last called custom event wasn't cancelled
set {packs::players::%loop-value's uuid%::pending} to {_id}
send loop-value packet {_packet}
on packet event play_client_resource_pack_status:
sync:
set {_id} to {packs::players::%player's uuid%::pending}
set {_details::*} to "%{_id}%" parsed as a number, player, event-packet, location of player and world of player
switch "%""ResourcePackStatus"" penum 0 of event-packet%":
case "ACCEPTED":
call custom event "resource pack accepted" to details {_details::*}
case "DECLINED":
call custom event "resource pack declined" to details {_details::*}
case "FAILED_DOWNLOAD":
call custom event "resource pack failed" to details {_details::*}
case "SUCCESSFULLY_LOADED":
call custom event "resource pack loaded" to details {_details::*}
MundoSK latest beta
code_language.skript:
evt "resource pack declined":
broadcast "%player% declined %getName(event-number)%"
evt "resource pack loaded":
broadcast "%player% loaded %getName(event-number)%"
evt "resource pack failed":
broadcast "%player% failed to download %getName(event-number)%"
evt "resource pack accepted":
broadcast "%player% accepted %getName(event-number)%"
Brewing shit
code_language.skript:
ce brew:
broadcast "%{_player}% made %{_pots::*}%"
code_language.skript:
on script load:
import "org.bukkit.Bukkit"
set {_rev::*} to ...{Bukkit}.getServer().getClass().getPackage().getName().replace("." and ",").split(",")
import "org.bukkit.craftbukkit.%{_rev::4}%.inventory.CraftItemStack"
import "net.minecraft.server.%{_rev::4}%.ItemStack" as {NMSItemStack}
import "net.minecraft.server.%{_rev::4}%.PotionBrewer"
import "org.bukkit.event.inventory.InventoryType"
import "org.bukkit.event.inventory.InventoryType$SlotType"
import "org.bukkit.event.inventory.ClickType"
on script unload:
delete {cache::brewing::*}
function nmsCopy(itemstack: item) :: object:
set {_itemstack} to try {_itemstack}.getRandom()
return {CraftItemStack}.asNMSCopy({_itemstack})
function bukkitCopy(nmsitem: object) :: item:
return {CraftItemStack}.asCraftMirror({_nmsitem})
function potionFrom(item1: item, item2: item) :: item:
set {_item1} to nmsCopy({_item1})
set {_item2} to nmsCopy({_item2})
set {_pot} to {PotionBrewer}.d({_item1} and {_item2})
return bukkitCopy({_pot})
on inventory click:
set {_inv} to event.getClickedInventory()
if {_inv}.getType() is {InventoryType}.BREWING!:
set {_loc} to {_inv}.getHolder().getLocation()
set {_loc} to "%{_loc}%||%world of {_loc}%"
set {cache::brewing::%{_loc}%} to player
set {cache::brewing::%{_loc}%::event} to event
on "org.bukkit.event.inventory.BrewEvent":
set {_inv} to event.getContents()
set {_holder} to {_inv}.getHolder()
set {_loc} to {_holder}.getLocation()
set {_str} to "%{_loc}%||%world of {_loc}%"
set {_event} to new ce "brew"
set {_player} in {_event} to {cache::brewing::%{_str}%}
set {_location} in {_event} to {_loc}
set {_block} in {_event} to {_holder}
set {_inventory} in {_event} to {_inv}
set {_world} in {_event} to world of {_location}
set {_event} in {_event} to {cache::brewing::%{_str}%::event}
set {_ingredient} to slot 3 of {_inv}
loop 3 times:
add potionFrom({_ingredient}, slot (loop-value - 1) of {_inv}) to {_pots::*}
set {_pots::*} in {_event} to {_pots::*}
call {_event}
Acara, skript-mirror
Recipe Grabber
code_language.skript:
function recipeTypeOf(item: item) :: string:
set {_item} to try {_item}.getRandom()
return (first element out of ...{api::bukkit}.getRecipesFor({_item})).getClass().getSimpleName()
function recipeOf(item: item) :: items:
set {_item} to try {_item}.getRandom()
switch (join split recipeTypeOf({_item}) at "Craft" with ""):
case "ShapedRecipe":
return ...((first element out of (...{api::bukkit}.getRecipesFor({_item}))).getIngredientMap().values())
case "FurnaceRecipe":
return ((first element out of (...{api::bukkit}.getRecipesFor({_item}))).getInput())
case "ShapelessRecipe":
return ...((first element out of (...{api::bukkit}.getRecipesFor({_item}))).getIngredientList())
case "MechantRecipe":
return ...((first element out of (...{api::bukkit}.getRecipesFor({_item}))).getIngredients())
return {_not set}
code_language.skript:
recipeOf(any craftable item)
code_language.skript:
set {_l::*} to recipeOf(wooden axe)
skript-mirror, MundoSK
Cancel Block Drops (potentially unsafe)
code_language.skript:
on script load:
import "org.bukkit.Bukkit"
set {_rev::*} to ...{Bukkit}.getServer().getClass().getPackage().getName().replace("." and ",").split(",")
import "net.minecraft.server.%{_rev::4}%.GameRules$EnumGameRuleType"
function getGameRule(world: world, gameRule: string) :: object:
return {_world}.getHandle().getGameRules().getBoolean({_gameRule})
function setGameRule(world: world, gameRule: string, type: string, to: string) :: object:
set {_args::*} to {_gameRule}, {_to} and {EnumGameRuleType}.valueOf({_type}.toUpperCase())
{_world}.getHandle().getGameRules().a({_args::*});
return getGameRule({_world}, {_gameRule})
function cancelDrops(event: event):
set {_world} to world of {_event}.getBlock()
getGameRule({_world}, "doTileDrops") is true
setGameRule({_world}, "doTileDrops", "BOOLEAN_VALUE", "false")
wait 1 tick
setGameRule({_world}, "doTileDrops", "BOOLEAN_VALUE", "true")
code_language.skript:
cancelDrops(block break event)
code_language.skript:
on break:
cancelDrops(event)
skript-mirror
Rotate a player's pitch/yaw without teleportation
code_language.skript:
on script load:
import "org.bukkit.Bukkit"
set {_rev::*} to ...{Bukkit}.getServer().getClass().getPackage().getName().replace("." and ",").split(",")
import "net.minecraft.server.%{_rev::4}%.PacketPlayOutPosition"
import "net.minecraft.server.%{_rev::4}%.PacketPlayOutPosition$EnumPlayerTeleportFlags" as {TPFlags}
import "java.util.Arrays"
import "ch.njol.skript.Skript"
import "java.util.stream.Collectors"
set {_flags::*} to ({TPFlags}.X!), ({TPFlags}.Y!), ({TPFlags}.Z!), ({TPFlags}.X_ROT!) and ({TPFlags}.Y_ROT!)
set {_flagArray} to [{_flags::*} as {TPFlags}]
set {crackshot::teleportation::set} to {Arrays}.stream({_flagArray}).collect({Collectors}.toSet())
effect rotate %players% by %number% horizontally [and %number% vertically]:
set {_args::*} to 0, 0, 0, expression 2, ((expression 3) ? 0), {crackshot::teleportation::set} and (({Skript}.isRunningMinecraft(1 and 9)) ? 1 : null)
set {_packet} to new {PacketPlayOutPosition}({_args::*})
loop expressions 1:
loop-value.getHandle().playerConnection!.sendPacket({_packet});
code_language.skript:
rotate %players% by %number% vertically [and %number% horizontally%
code_language.skript:
on join:
rotate player by 10 vertically and 50 horizontally
skript-mirror
NPCs
Cancelled. See below.
Last edited: