[{"data":1,"prerenderedAt":1355},["ShallowReactive",2],{"navigation":3,"reference-navigation":62,"\u002Fdocs\u002Fevent-system":365,"\u002Fdocs\u002Fevent-system-surround":1350},[4,22,26,30,34,38,42,46,50,54,58],{"title":5,"path":6,"stem":7,"children":8},"Bundle Developer","\u002Fdocs\u002Fbundle-developer","1.docs\u002F1.bundle-developer\u002Findex",[9,10,14,18],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Terminology","\u002Fdocs\u002Fbundle-developer\u002Fterminology","1.docs\u002F1.bundle-developer\u002F1.terminology",{"title":15,"path":16,"stem":17},"Prerequisites","\u002Fdocs\u002Fbundle-developer\u002Fprerequisites","1.docs\u002F1.bundle-developer\u002F2.prerequisites",{"title":19,"path":20,"stem":21},"Bundle Layout","\u002Fdocs\u002Fbundle-developer\u002Flayout","1.docs\u002F1.bundle-developer\u002F3.layout",{"title":23,"path":24,"stem":25},"Custom Registry Developer Guide","\u002Fdocs\u002Fcustom-registries","1.docs\u002Fcustom-registries",{"title":27,"path":28,"stem":29},"Defining Bundle Entities","\u002Fdocs\u002Fdefining-bundle-entities","1.docs\u002Fdefining-bundle-entities",{"title":31,"path":32,"stem":33},"Defining Bundle Sounds","\u002Fdocs\u002Fdefining-bundle-sounds","1.docs\u002Fdefining-bundle-sounds",{"title":35,"path":36,"stem":37},"Defining Bundle Tile Transitions","\u002Fdocs\u002Fdefining-bundle-tile-transitions","1.docs\u002Fdefining-bundle-tile-transitions",{"title":39,"path":40,"stem":41},"Defining Bundle Tiles","\u002Fdocs\u002Fdefining-bundle-tiles","1.docs\u002Fdefining-bundle-tiles",{"title":43,"path":44,"stem":45},"Defining Bundle Visuals","\u002Fdocs\u002Fdefining-bundle-visuals","1.docs\u002Fdefining-bundle-visuals",{"title":47,"path":48,"stem":49},"Bundle Event System Developer Guide","\u002Fdocs\u002Fevent-system","1.docs\u002Fevent-system",{"title":51,"path":52,"stem":53},"Getting Started with Selene Bundles","\u002Fdocs\u002Fgetting-started-bundles","1.docs\u002Fgetting-started-bundles",{"title":55,"path":56,"stem":57},"Making Resource Packs","\u002Fdocs\u002Fmaking-resource-packs","1.docs\u002Fmaking-resource-packs",{"title":59,"path":60,"stem":61},"Bundle Network API Developer Guide","\u002Fdocs\u002Fnetwork-apis","1.docs\u002Fnetwork-apis",[63,212,253],{"title":64,"path":65,"stem":66,"children":67,"page":121},"Modules","\u002Freference\u002Fmodules","2.reference\u002F1.modules",[68,122,167],{"title":69,"path":70,"stem":71,"children":72,"page":121},"Common","\u002Freference\u002Fmodules\u002Fcommon","2.reference\u002F1.modules\u002F1.common",[73,77,81,85,89,93,97,101,105,109,113,117],{"title":74,"path":75,"stem":76},"debug","\u002Freference\u002Fmodules\u002Fcommon\u002Fdebug","2.reference\u002F1.modules\u002F1.common\u002Fdebug",{"title":78,"path":79,"stem":80},"mathx","\u002Freference\u002Fmodules\u002Fcommon\u002Fmathx","2.reference\u002F1.modules\u002F1.common\u002Fmathx",{"title":82,"path":83,"stem":84},"os","\u002Freference\u002Fmodules\u002Fcommon\u002Fos","2.reference\u002F1.modules\u002F1.common\u002Fos",{"title":86,"path":87,"stem":88},"package","\u002Freference\u002Fmodules\u002Fcommon\u002Fpackage","2.reference\u002F1.modules\u002F1.common\u002Fpackage",{"title":90,"path":91,"stem":92},"selene.grid","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.grid","2.reference\u002F1.modules\u002F1.common\u002Fselene.grid",{"title":94,"path":95,"stem":96},"selene.http","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.http","2.reference\u002F1.modules\u002F1.common\u002Fselene.http",{"title":98,"path":99,"stem":100},"selene.i18n","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.i18n","2.reference\u002F1.modules\u002F1.common\u002Fselene.i18n",{"title":102,"path":103,"stem":104},"selene.registries","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.registries","2.reference\u002F1.modules\u002F1.common\u002Fselene.registries",{"title":106,"path":107,"stem":108},"selene.resources","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.resources","2.reference\u002F1.modules\u002F1.common\u002Fselene.resources",{"title":110,"path":111,"stem":112},"selene.schedules","\u002Freference\u002Fmodules\u002Fcommon\u002Fselene.schedules","2.reference\u002F1.modules\u002F1.common\u002Fselene.schedules",{"title":114,"path":115,"stem":116},"stringx","\u002Freference\u002Fmodules\u002Fcommon\u002Fstringx","2.reference\u002F1.modules\u002F1.common\u002Fstringx",{"title":118,"path":119,"stem":120},"tablex","\u002Freference\u002Fmodules\u002Fcommon\u002Ftablex","2.reference\u002F1.modules\u002F1.common\u002Ftablex",false,{"title":123,"path":124,"stem":125,"children":126,"page":121},"Server","\u002Freference\u002Fmodules\u002Fserver","2.reference\u002F1.modules\u002F2.server",[127,131,135,139,143,147,151,155,159,163],{"title":128,"path":129,"stem":130},"selene.attributes","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.attributes","2.reference\u002F1.modules\u002F2.server\u002Fselene.attributes",{"title":132,"path":133,"stem":134},"selene.config","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.config","2.reference\u002F1.modules\u002F2.server\u002Fselene.config",{"title":136,"path":137,"stem":138},"selene.dimensions","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.dimensions","2.reference\u002F1.modules\u002F2.server\u002Fselene.dimensions",{"title":140,"path":141,"stem":142},"selene.entities","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.entities","2.reference\u002F1.modules\u002F2.server\u002Fselene.entities",{"title":144,"path":145,"stem":146},"selene.map","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.map","2.reference\u002F1.modules\u002F2.server\u002Fselene.map",{"title":148,"path":149,"stem":150},"selene.network","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.network","2.reference\u002F1.modules\u002F2.server\u002Fselene.network",{"title":152,"path":153,"stem":154},"selene.players","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.players","2.reference\u002F1.modules\u002F2.server\u002Fselene.players",{"title":156,"path":157,"stem":158},"selene.saves","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.saves","2.reference\u002F1.modules\u002F2.server\u002Fselene.saves",{"title":160,"path":161,"stem":162},"selene.server","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.server","2.reference\u002F1.modules\u002F2.server\u002Fselene.server",{"title":164,"path":165,"stem":166},"selene.sounds","\u002Freference\u002Fmodules\u002Fserver\u002Fselene.sounds","2.reference\u002F1.modules\u002F2.server\u002Fselene.sounds",{"title":168,"path":169,"stem":170,"children":171,"page":121},"Client","\u002Freference\u002Fmodules\u002Fclient","2.reference\u002F1.modules\u002F3.client",[172,176,179,183,187,190,194,197,200,204,208],{"title":173,"path":174,"stem":175},"selene.camera","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.camera","2.reference\u002F1.modules\u002F3.client\u002Fselene.camera",{"title":140,"path":177,"stem":178},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.entities","2.reference\u002F1.modules\u002F3.client\u002Fselene.entities",{"title":180,"path":181,"stem":182},"selene.game","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.game","2.reference\u002F1.modules\u002F3.client\u002Fselene.game",{"title":184,"path":185,"stem":186},"selene.input","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.input","2.reference\u002F1.modules\u002F3.client\u002Fselene.input",{"title":144,"path":188,"stem":189},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.map","2.reference\u002F1.modules\u002F3.client\u002Fselene.map",{"title":191,"path":192,"stem":193},"selene.movement.grid","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.movement.grid","2.reference\u002F1.modules\u002F3.client\u002Fselene.movement.grid",{"title":148,"path":195,"stem":196},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.network","2.reference\u002F1.modules\u002F3.client\u002Fselene.network",{"title":164,"path":198,"stem":199},"\u002Freference\u002Fmodules\u002Fclient\u002Fselene.sounds","2.reference\u002F1.modules\u002F3.client\u002Fselene.sounds",{"title":201,"path":202,"stem":203},"selene.textures","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.textures","2.reference\u002F1.modules\u002F3.client\u002Fselene.textures",{"title":205,"path":206,"stem":207},"selene.ui.lml","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.ui.lml","2.reference\u002F1.modules\u002F3.client\u002Fselene.ui.lml",{"title":209,"path":210,"stem":211},"selene.visuals","\u002Freference\u002Fmodules\u002Fclient\u002Fselene.visuals","2.reference\u002F1.modules\u002F3.client\u002Fselene.visuals",{"title":213,"path":214,"stem":215,"children":216,"page":121},"Data","\u002Freference\u002Fdata","2.reference\u002F2.data",[217,241],{"title":69,"path":218,"stem":219,"children":220,"page":121},"\u002Freference\u002Fdata\u002Fcommon","2.reference\u002F2.data\u002F1.common",[221,225,229,233,237],{"title":222,"path":223,"stem":224},"Component Definition","\u002Freference\u002Fdata\u002Fcommon\u002Fcomponentdefinition","2.reference\u002F2.data\u002F1.common\u002FComponentDefinition",{"title":226,"path":227,"stem":228},"Entity Definition","\u002Freference\u002Fdata\u002Fcommon\u002Fentitydefinition","2.reference\u002F2.data\u002F1.common\u002FEntityDefinition",{"title":230,"path":231,"stem":232},"Sound Definition","\u002Freference\u002Fdata\u002Fcommon\u002Fsounddefinition","2.reference\u002F2.data\u002F1.common\u002FSoundDefinition",{"title":234,"path":235,"stem":236},"Tile Definition","\u002Freference\u002Fdata\u002Fcommon\u002Ftiledefinition","2.reference\u002F2.data\u002F1.common\u002FTileDefinition",{"title":238,"path":239,"stem":240},"Transition Definition","\u002Freference\u002Fdata\u002Fcommon\u002Ftransitiondefinition","2.reference\u002F2.data\u002F1.common\u002FTransitionDefinition",{"title":168,"path":242,"stem":243,"children":244,"page":121},"\u002Freference\u002Fdata\u002Fclient","2.reference\u002F2.data\u002F3.client",[245,249],{"title":246,"path":247,"stem":248},"Audio Definition","\u002Freference\u002Fdata\u002Fclient\u002Faudiodefinition","2.reference\u002F2.data\u002F3.client\u002FAudioDefinition",{"title":250,"path":251,"stem":252},"Visual Definition","\u002Freference\u002Fdata\u002Fclient\u002Fvisualdefinition","2.reference\u002F2.data\u002F3.client\u002FVisualDefinition",{"title":254,"path":255,"stem":256,"children":257,"page":121},"Classes","\u002Freference\u002Fclasses","2.reference\u002F3.classes",[258,286,318],{"title":69,"path":259,"stem":260,"children":261,"page":121},"\u002Freference\u002Fclasses\u002Fcommon","2.reference\u002F3.classes\u002F1.common",[262,266,270,274,278,282],{"title":263,"path":264,"stem":265},"Coordinate","\u002Freference\u002Fclasses\u002Fcommon\u002Fcoordinate","2.reference\u002F3.classes\u002F1.common\u002FCoordinate",{"title":267,"path":268,"stem":269},"CustomRegistryObject","\u002Freference\u002Fclasses\u002Fcommon\u002Fcustomregistryobject","2.reference\u002F3.classes\u002F1.common\u002FCustomRegistryObject",{"title":271,"path":272,"stem":273},"LuaReference","\u002Freference\u002Fclasses\u002Fcommon\u002Fluareference","2.reference\u002F3.classes\u002F1.common\u002FLuaReference",{"title":275,"path":276,"stem":277},"Observable","\u002Freference\u002Fclasses\u002Fcommon\u002Fobservable","2.reference\u002F3.classes\u002F1.common\u002FObservable",{"title":279,"path":280,"stem":281},"RegistryObject","\u002Freference\u002Fclasses\u002Fcommon\u002Fregistryobject","2.reference\u002F3.classes\u002F1.common\u002FRegistryObject",{"title":283,"path":284,"stem":285},"Signal","\u002Freference\u002Fclasses\u002Fcommon\u002Fsignal","2.reference\u002F3.classes\u002F1.common\u002FSignal",{"title":123,"path":287,"stem":288,"children":289,"page":121},"\u002Freference\u002Fclasses\u002Fserver","2.reference\u002F3.classes\u002F2.server",[290,294,298,302,306,310,314],{"title":291,"path":292,"stem":293},"Dimension","\u002Freference\u002Fclasses\u002Fserver\u002Fdimension","2.reference\u002F3.classes\u002F2.server\u002FDimension",{"title":295,"path":296,"stem":297},"Entity","\u002Freference\u002Fclasses\u002Fserver\u002Fentity","2.reference\u002F3.classes\u002F2.server\u002FEntity",{"title":299,"path":300,"stem":301},"LoginQueueEntry","\u002Freference\u002Fclasses\u002Fserver\u002Floginqueueentry","2.reference\u002F3.classes\u002F2.server\u002FLoginQueueEntry",{"title":303,"path":304,"stem":305},"MapTree","\u002Freference\u002Fclasses\u002Fserver\u002Fmaptree","2.reference\u002F3.classes\u002F2.server\u002FMapTree",{"title":307,"path":308,"stem":309},"Player","\u002Freference\u002Fclasses\u002Fserver\u002Fplayer","2.reference\u002F3.classes\u002F2.server\u002FPlayer",{"title":311,"path":312,"stem":313},"ScopedChunkView","\u002Freference\u002Fclasses\u002Fserver\u002Fscopedchunkview","2.reference\u002F3.classes\u002F2.server\u002FScopedChunkView",{"title":315,"path":316,"stem":317},"TransientTile","\u002Freference\u002Fclasses\u002Fserver\u002Ftransienttile","2.reference\u002F3.classes\u002F2.server\u002FTransientTile",{"title":168,"path":319,"stem":320,"children":321,"page":121},"\u002Freference\u002Fclasses\u002Fclient","2.reference\u002F3.classes\u002F3.client",[322,326,330,334,337,341,345,349,353,357,361],{"title":323,"path":324,"stem":325},"Actor","\u002Freference\u002Fclasses\u002Fclient\u002Factor","2.reference\u002F3.classes\u002F3.client\u002FActor",{"title":327,"path":328,"stem":329},"Drawable","\u002Freference\u002Fclasses\u002Fclient\u002Fdrawable","2.reference\u002F3.classes\u002F3.client\u002FDrawable",{"title":331,"path":332,"stem":333},"DrawableVisual2D","\u002Freference\u002Fclasses\u002Fclient\u002Fdrawablevisual2d","2.reference\u002F3.classes\u002F3.client\u002FDrawableVisual2D",{"title":295,"path":335,"stem":336},"\u002Freference\u002Fclasses\u002Fclient\u002Fentity","2.reference\u002F3.classes\u002F3.client\u002FEntity",{"title":338,"path":339,"stem":340},"IsoVisualComponent","\u002Freference\u002Fclasses\u002Fclient\u002Fisovisualcomponent","2.reference\u002F3.classes\u002F3.client\u002FIsoVisualComponent",{"title":342,"path":343,"stem":344},"LuaTexture","\u002Freference\u002Fclasses\u002Fclient\u002Fluatexture","2.reference\u002F3.classes\u002F3.client\u002FLuaTexture",{"title":346,"path":347,"stem":348},"Skin","\u002Freference\u002Fclasses\u002Fclient\u002Fskin","2.reference\u002F3.classes\u002F3.client\u002FSkin",{"title":350,"path":351,"stem":352},"TextFieldTextFieldClickListener","\u002Freference\u002Fclasses\u002Fclient\u002Ftextfield.textfieldclicklistener","2.reference\u002F3.classes\u002F3.client\u002FTextField.TextFieldClickListener",{"title":354,"path":355,"stem":356},"Tile","\u002Freference\u002Fclasses\u002Fclient\u002Ftile","2.reference\u002F3.classes\u002F3.client\u002FTile",{"title":358,"path":359,"stem":360},"Visual2D","\u002Freference\u002Fclasses\u002Fclient\u002Fvisual2d","2.reference\u002F3.classes\u002F3.client\u002FVisual2D",{"title":362,"path":363,"stem":364},"Visual2DComponent","\u002Freference\u002Fclasses\u002Fclient\u002Fvisual2dcomponent","2.reference\u002F3.classes\u002F3.client\u002FVisual2DComponent",{"id":366,"title":47,"body":367,"description":1345,"extension":1346,"meta":1347,"navigation":404,"path":48,"seo":1348,"stem":49,"__hash__":1349},"docs\u002F1.docs\u002Fevent-system.md",{"type":368,"value":369,"toc":1326},"minimark",[370,374,378,381,424,427,432,435,454,457,485,492,496,499,523,526,530,533,539,557,585,645,649,652,657,705,746,751,754,824,906,911,916,923,967,1015,1023,1027,1030,1035,1038,1071,1097,1102,1130,1156,1161,1164,1192,1230,1235,1263,1291,1295,1311,1322],[371,372,47],"h1",{"id":373},"bundle-event-system-developer-guide",[375,376,377],"p",{},"Selene exposes engine events to bundle Lua as callable event fields on Lua modules. Use them when your bundle needs to react to lifecycle changes, player activity, entity movement, map updates, camera changes, or periodic ticks without polling.",[375,379,380],{},"Events are exposed through the same module system as the rest of the bundle API:",[382,383,388],"pre",{"className":384,"code":385,"language":386,"meta":387,"style":387},"language-lua shiki shiki-themes github-light github-dark","local Server = require(\"selene.server\")\n\nServer.serverStarted(function()\n  print(\"Server is ready\")\nend)\n","lua","",[389,390,391,399,406,412,418],"code",{"__ignoreMap":387},[392,393,396],"span",{"class":394,"line":395},"line",1,[392,397,398],{},"local Server = require(\"selene.server\")\n",[392,400,402],{"class":394,"line":401},2,[392,403,405],{"emptyLinePlaceholder":404},true,"\n",[392,407,409],{"class":394,"line":408},3,[392,410,411],{},"Server.serverStarted(function()\n",[392,413,415],{"class":394,"line":414},4,[392,416,417],{},"  print(\"Server is ready\")\n",[392,419,421],{"class":394,"line":420},5,[392,422,423],{},"end)\n",[375,425,426],{},"The event field is the registration function. Call it once with a callback from an entrypoint or from a module loaded by an entrypoint.",[428,429,431],"h2",{"id":430},"event-registration","Event registration",[375,433,434],{},"Every exposed event follows this shape:",[382,436,438],{"className":384,"code":437,"language":386,"meta":387,"style":387},"Module.eventName(function(...)\n  -- event-specific arguments\nend)\n",[389,439,440,445,450],{"__ignoreMap":387},[392,441,442],{"class":394,"line":395},[392,443,444],{},"Module.eventName(function(...)\n",[392,446,447],{"class":394,"line":401},[392,448,449],{},"  -- event-specific arguments\n",[392,451,452],{"class":394,"line":408},[392,453,423],{},[375,455,456],{},"For example, server entity movement events pass the entity and the affected coordinate:",[382,458,460],{"className":384,"code":459,"language":386,"meta":387,"style":387},"local Entities = require(\"selene.entities\")\n\nEntities.steppedOnTile(function(entity, coordinate)\n  print(entity:getName(), coordinate.x, coordinate.y, coordinate.z)\nend)\n",[389,461,462,467,471,476,481],{"__ignoreMap":387},[392,463,464],{"class":394,"line":395},[392,465,466],{},"local Entities = require(\"selene.entities\")\n",[392,468,469],{"class":394,"line":401},[392,470,405],{"emptyLinePlaceholder":404},[392,472,473],{"class":394,"line":408},[392,474,475],{},"Entities.steppedOnTile(function(entity, coordinate)\n",[392,477,478],{"class":394,"line":414},[392,479,480],{},"  print(entity:getName(), coordinate.x, coordinate.y, coordinate.z)\n",[392,482,483],{"class":394,"line":420},[392,484,423],{},[375,486,487,488,491],{},"Event callbacks run in the bundle context that registered them. This matters for bundle-relative module loading and runtime ownership: if bundle ",[389,489,490],{},"myworld"," registers a callback, Selene restores that bundle context when the callback is invoked.",[428,493,495],{"id":494},"callback-behavior","Callback behavior",[375,497,498],{},"Most events call every registered listener in registration order. Keep callbacks short and deterministic:",[500,501,502,506,517,520],"ul",{},[503,504,505],"li",{},"Do lightweight checks first and return early when the event is not relevant.",[503,507,508,509,512,513,516],{},"Avoid expensive work in high-frequency events such as ",[389,510,511],{},"selene.game.preTick"," and ",[389,514,515],{},"selene.schedules.everySecond",".",[503,518,519],{},"Do not register the same event repeatedly inside another event callback unless you intentionally want multiple listeners.",[503,521,522],{},"Treat client-side events as presentation hooks and keep authoritative game decisions on the server.",[375,524,525],{},"Lua errors are reported with the registration trace captured when the callback was connected. Entity tile events also isolate listener failures so one failing listener does not prevent later listeners from running.",[428,527,529],{"id":528},"common-events","Common events",[375,531,532],{},"Common events are available to both client and server bundle entrypoints.",[534,535,537],"h3",{"id":536},"seleneschedules",[389,538,110],{},[375,540,541,542,545,546,545,549,552,553,556],{},"Use scheduled events for coarse periodic work. For precise timers or cancelable repeated work, use ",[389,543,544],{},"setTimeout",", ",[389,547,548],{},"clearTimeout",[389,550,551],{},"setInterval",", and ",[389,554,555],{},"clearInterval"," from the same module.",[382,558,560],{"className":384,"code":559,"language":386,"meta":387,"style":387},"local Schedules = require(\"selene.schedules\")\n\nSchedules.everyMinute(function()\n  print(\"A minute passed\")\nend)\n",[389,561,562,567,571,576,581],{"__ignoreMap":387},[392,563,564],{"class":394,"line":395},[392,565,566],{},"local Schedules = require(\"selene.schedules\")\n",[392,568,569],{"class":394,"line":401},[392,570,405],{"emptyLinePlaceholder":404},[392,572,573],{"class":394,"line":408},[392,574,575],{},"Schedules.everyMinute(function()\n",[392,577,578],{"class":394,"line":414},[392,579,580],{},"  print(\"A minute passed\")\n",[392,582,583],{"class":394,"line":420},[392,584,423],{},[586,587,588,604],"table",{},[589,590,591],"thead",{},[592,593,594,598,601],"tr",{},[595,596,597],"th",{},"Event",[595,599,600],{},"Arguments",[595,602,603],{},"When it fires",[605,606,607,621,633],"tbody",{},[592,608,609,615,618],{},[610,611,612],"td",{},[389,613,614],{},"everySecond",[610,616,617],{},"none",[610,619,620],{},"Once per second.",[592,622,623,628,630],{},[610,624,625],{},[389,626,627],{},"everyMinute",[610,629,617],{},[610,631,632],{},"Once per full minute.",[592,634,635,640,642],{},[610,636,637],{},[389,638,639],{},"everyHour",[610,641,617],{},[610,643,644],{},"Once per full hour.",[428,646,648],{"id":647},"server-events","Server events",[375,650,651],{},"Server events are available from server and common entrypoints running on the server.",[534,653,655],{"id":654},"seleneserver",[389,656,160],{},[382,658,660],{"className":384,"code":659,"language":386,"meta":387,"style":387},"local Server = require(\"selene.server\")\n\nServer.serverStarted(function()\n  print(\"Server started\")\nend)\n\nServer.serverReloaded(function()\n  print(\"Server data was loaded or reloaded\")\nend)\n",[389,661,662,666,670,674,679,683,688,694,700],{"__ignoreMap":387},[392,663,664],{"class":394,"line":395},[392,665,398],{},[392,667,668],{"class":394,"line":401},[392,669,405],{"emptyLinePlaceholder":404},[392,671,672],{"class":394,"line":408},[392,673,411],{},[392,675,676],{"class":394,"line":414},[392,677,678],{},"  print(\"Server started\")\n",[392,680,681],{"class":394,"line":420},[392,682,423],{},[392,684,686],{"class":394,"line":685},6,[392,687,405],{"emptyLinePlaceholder":404},[392,689,691],{"class":394,"line":690},7,[392,692,693],{},"Server.serverReloaded(function()\n",[392,695,697],{"class":394,"line":696},8,[392,698,699],{},"  print(\"Server data was loaded or reloaded\")\n",[392,701,703],{"class":394,"line":702},9,[392,704,423],{},[586,706,707,717],{},[589,708,709],{},[592,710,711,713,715],{},[595,712,597],{},[595,714,600],{},[595,716,603],{},[605,718,719,731],{},[592,720,721,726,728],{},[610,722,723],{},[389,724,725],{},"serverStarted",[610,727,617],{},[610,729,730],{},"During server startup, before the HTTP server, network server, heartbeat, bundle watcher, and main event loop are started.",[592,732,733,738,740],{},[610,734,735],{},[389,736,737],{},"serverReloaded",[610,739,617],{},[610,741,742,743,745],{},"During server startup after ",[389,744,725],{},". The event exists as the reload hook for server data and bundle state.",[534,747,749],{"id":748},"seleneplayers",[389,750,152],{},[375,752,753],{},"Player events cover the login queue and connected players.",[382,755,757],{"className":384,"code":756,"language":386,"meta":387,"style":387},"local Players = require(\"selene.players\")\n\nPlayers.playerQueued(function(entry)\n  if shouldReject(entry:getUserId()) then\n    entry:reject(\"Access denied\")\n  else\n    entry:accept()\n  end\nend)\n\nPlayers.playerJoined(function(player)\n  print(\"Joined:\", player:getName())\nend)\n",[389,758,759,764,768,773,778,783,788,793,798,802,807,813,819],{"__ignoreMap":387},[392,760,761],{"class":394,"line":395},[392,762,763],{},"local Players = require(\"selene.players\")\n",[392,765,766],{"class":394,"line":401},[392,767,405],{"emptyLinePlaceholder":404},[392,769,770],{"class":394,"line":408},[392,771,772],{},"Players.playerQueued(function(entry)\n",[392,774,775],{"class":394,"line":414},[392,776,777],{},"  if shouldReject(entry:getUserId()) then\n",[392,779,780],{"class":394,"line":420},[392,781,782],{},"    entry:reject(\"Access denied\")\n",[392,784,785],{"class":394,"line":685},[392,786,787],{},"  else\n",[392,789,790],{"class":394,"line":690},[392,791,792],{},"    entry:accept()\n",[392,794,795],{"class":394,"line":696},[392,796,797],{},"  end\n",[392,799,800],{"class":394,"line":702},[392,801,423],{},[392,803,805],{"class":394,"line":804},10,[392,806,405],{"emptyLinePlaceholder":404},[392,808,810],{"class":394,"line":809},11,[392,811,812],{},"Players.playerJoined(function(player)\n",[392,814,816],{"class":394,"line":815},12,[392,817,818],{},"  print(\"Joined:\", player:getName())\n",[392,820,822],{"class":394,"line":821},13,[392,823,423],{},[586,825,826,836],{},[589,827,828],{},[592,829,830,832,834],{},[595,831,597],{},[595,833,600],{},[595,835,603],{},[605,837,838,863,877,892],{},[592,839,840,845,850],{},[610,841,842],{},[389,843,844],{},"playerQueued",[610,846,847],{},[389,848,849],{},"LoginQueueEntry entry",[610,851,852,853,545,856,859,860,516],{},"A user enters or updates their login queue entry. The callback can call ",[389,854,855],{},"entry:accept()",[389,857,858],{},"entry:reject(message)",", or ",[389,861,862],{},"entry:notify(message)",[592,864,865,870,874],{},[610,866,867],{},[389,868,869],{},"playerDequeued",[610,871,872],{},[389,873,849],{},[610,875,876],{},"A user is removed from the login queue.",[592,878,879,884,889],{},[610,880,881],{},[389,882,883],{},"playerJoined",[610,885,886],{},[389,887,888],{},"Player player",[610,890,891],{},"A player finishes authentication and joins the game.",[592,893,894,899,903],{},[610,895,896],{},[389,897,898],{},"playerLeft",[610,900,901],{},[389,902,888],{},[610,904,905],{},"A connected player disconnects and is removed from the player manager.",[375,907,908,910],{},[389,909,844],{}," is special because the queue entry's final status controls the login result. If multiple listeners are registered, later listeners can overwrite the status set by earlier listeners.",[534,912,914],{"id":913},"seleneentities",[389,915,140],{},[375,917,918,919,922],{},"Entity events fire for server-side entity movement performed through movement logic such as ",[389,920,921],{},"entity:move(direction)",". Direct coordinate changes that teleport an entity do not emit stepped-on or stepped-off tile events.",[382,924,926],{"className":384,"code":925,"language":386,"meta":387,"style":387},"local Entities = require(\"selene.entities\")\n\nEntities.steppedOffTile(function(entity, coordinate)\n  print(entity:getName(), \"left\", coordinate.x, coordinate.y, coordinate.z)\nend)\n\nEntities.steppedOnTile(function(entity, coordinate)\n  print(entity:getName(), \"entered\", coordinate.x, coordinate.y, coordinate.z)\nend)\n",[389,927,928,932,936,941,946,950,954,958,963],{"__ignoreMap":387},[392,929,930],{"class":394,"line":395},[392,931,466],{},[392,933,934],{"class":394,"line":401},[392,935,405],{"emptyLinePlaceholder":404},[392,937,938],{"class":394,"line":408},[392,939,940],{},"Entities.steppedOffTile(function(entity, coordinate)\n",[392,942,943],{"class":394,"line":414},[392,944,945],{},"  print(entity:getName(), \"left\", coordinate.x, coordinate.y, coordinate.z)\n",[392,947,948],{"class":394,"line":420},[392,949,423],{},[392,951,952],{"class":394,"line":685},[392,953,405],{"emptyLinePlaceholder":404},[392,955,956],{"class":394,"line":690},[392,957,475],{},[392,959,960],{"class":394,"line":696},[392,961,962],{},"  print(entity:getName(), \"entered\", coordinate.x, coordinate.y, coordinate.z)\n",[392,964,965],{"class":394,"line":702},[392,966,423],{},[586,968,969,979],{},[589,970,971],{},[592,972,973,975,977],{},[595,974,597],{},[595,976,600],{},[595,978,603],{},[605,980,981,999],{},[592,982,983,988,996],{},[610,984,985],{},[389,986,987],{},"steppedOffTile",[610,989,990,545,993],{},[389,991,992],{},"Entity entity",[389,994,995],{},"Coordinate coordinate",[610,997,998],{},"After a successful entity move, for the previous coordinate.",[592,1000,1001,1006,1012],{},[610,1002,1003],{},[389,1004,1005],{},"steppedOnTile",[610,1007,1008,545,1010],{},[389,1009,992],{},[389,1011,995],{},[610,1013,1014],{},"After a successful entity move, for the new coordinate.",[375,1016,1017,1018,1020,1021,516],{},"For a successful move, ",[389,1019,987],{}," fires before ",[389,1022,1005],{},[428,1024,1026],{"id":1025},"client-events","Client events",[375,1028,1029],{},"Client events are available from client and common entrypoints running on the client.",[534,1031,1033],{"id":1032},"seleneuilml",[389,1034,205],{},[375,1036,1037],{},"Use the UI setup event to create HUD widgets, load LML files, or attach UI actors after client bundle entrypoints have loaded.",[382,1039,1041],{"className":384,"code":1040,"language":386,"meta":387,"style":387},"local UI = require(\"selene.ui.lml\")\n\nUI.setup(function()\n  local hud = UI.loadUI(\"my-bundle\u002Fclient\u002Fui\u002Fhud.xml\")\n  UI.addToRoot(hud)\nend)\n",[389,1042,1043,1048,1052,1057,1062,1067],{"__ignoreMap":387},[392,1044,1045],{"class":394,"line":395},[392,1046,1047],{},"local UI = require(\"selene.ui.lml\")\n",[392,1049,1050],{"class":394,"line":401},[392,1051,405],{"emptyLinePlaceholder":404},[392,1053,1054],{"class":394,"line":408},[392,1055,1056],{},"UI.setup(function()\n",[392,1058,1059],{"class":394,"line":414},[392,1060,1061],{},"  local hud = UI.loadUI(\"my-bundle\u002Fclient\u002Fui\u002Fhud.xml\")\n",[392,1063,1064],{"class":394,"line":420},[392,1065,1066],{},"  UI.addToRoot(hud)\n",[392,1068,1069],{"class":394,"line":685},[392,1070,423],{},[586,1072,1073,1083],{},[589,1074,1075],{},[592,1076,1077,1079,1081],{},[595,1078,597],{},[595,1080,600],{},[595,1082,603],{},[605,1084,1085],{},[592,1086,1087,1092,1094],{},[610,1088,1089],{},[389,1090,1091],{},"setup",[610,1093,617],{},[610,1095,1096],{},"Once during client startup after client and common bundle entrypoints are loaded and client registries are initialized.",[534,1098,1100],{"id":1099},"selenegame",[389,1101,180],{},[382,1103,1105],{"className":384,"code":1104,"language":386,"meta":387,"style":387},"local Game = require(\"selene.game\")\n\nGame.preTick(function()\n  -- Runs every rendered frame before input, movement, camera, and drawable updates.\nend)\n",[389,1106,1107,1112,1116,1121,1126],{"__ignoreMap":387},[392,1108,1109],{"class":394,"line":395},[392,1110,1111],{},"local Game = require(\"selene.game\")\n",[392,1113,1114],{"class":394,"line":401},[392,1115,405],{"emptyLinePlaceholder":404},[392,1117,1118],{"class":394,"line":408},[392,1119,1120],{},"Game.preTick(function()\n",[392,1122,1123],{"class":394,"line":414},[392,1124,1125],{},"  -- Runs every rendered frame before input, movement, camera, and drawable updates.\n",[392,1127,1128],{"class":394,"line":420},[392,1129,423],{},[586,1131,1132,1142],{},[589,1133,1134],{},[592,1135,1136,1138,1140],{},[595,1137,597],{},[595,1139,600],{},[595,1141,603],{},[605,1143,1144],{},[592,1145,1146,1151,1153],{},[610,1147,1148],{},[389,1149,1150],{},"preTick",[610,1152,617],{},[610,1154,1155],{},"Every client render frame, before network work, pending bundle updates, input, movement, camera, and drawable updates.",[534,1157,1159],{"id":1158},"selenemap",[389,1160,144],{},[375,1162,1163],{},"Map events are client-side notifications about visible map data changes.",[382,1165,1167],{"className":384,"code":1166,"language":386,"meta":387,"style":387},"local Map = require(\"selene.map\")\n\nMap.onChunkChanged(function(coordinate, width, height)\n  print(\"Map changed at\", coordinate.x, coordinate.y, coordinate.z, width, height)\nend)\n",[389,1168,1169,1174,1178,1183,1188],{"__ignoreMap":387},[392,1170,1171],{"class":394,"line":395},[392,1172,1173],{},"local Map = require(\"selene.map\")\n",[392,1175,1176],{"class":394,"line":401},[392,1177,405],{"emptyLinePlaceholder":404},[392,1179,1180],{"class":394,"line":408},[392,1181,1182],{},"Map.onChunkChanged(function(coordinate, width, height)\n",[392,1184,1185],{"class":394,"line":414},[392,1186,1187],{},"  print(\"Map changed at\", coordinate.x, coordinate.y, coordinate.z, width, height)\n",[392,1189,1190],{"class":394,"line":420},[392,1191,423],{},[586,1193,1194,1204],{},[589,1195,1196],{},[592,1197,1198,1200,1202],{},[595,1199,597],{},[595,1201,600],{},[595,1203,603],{},[605,1205,1206],{},[592,1207,1208,1213,1223],{},[610,1209,1210],{},[389,1211,1212],{},"onChunkChanged",[610,1214,1215,545,1217,545,1220],{},[389,1216,995],{},[389,1218,1219],{},"number width",[389,1221,1222],{},"number height",[610,1224,1225,1226,1229],{},"A client map chunk or individual tile area changes. ",[389,1227,1228],{},"coordinate"," is the changed area's origin.",[534,1231,1233],{"id":1232},"selenecamera",[389,1234,173],{},[382,1236,1238],{"className":384,"code":1237,"language":386,"meta":387,"style":387},"local Camera = require(\"selene.camera\")\n\nCamera.onCoordinateChanged(function(coordinate)\n  print(\"Camera moved to\", coordinate.x, coordinate.y, coordinate.z)\nend)\n",[389,1239,1240,1245,1249,1254,1259],{"__ignoreMap":387},[392,1241,1242],{"class":394,"line":395},[392,1243,1244],{},"local Camera = require(\"selene.camera\")\n",[392,1246,1247],{"class":394,"line":401},[392,1248,405],{"emptyLinePlaceholder":404},[392,1250,1251],{"class":394,"line":408},[392,1252,1253],{},"Camera.onCoordinateChanged(function(coordinate)\n",[392,1255,1256],{"class":394,"line":414},[392,1257,1258],{},"  print(\"Camera moved to\", coordinate.x, coordinate.y, coordinate.z)\n",[392,1260,1261],{"class":394,"line":420},[392,1262,423],{},[586,1264,1265,1275],{},[589,1266,1267],{},[592,1268,1269,1271,1273],{},[595,1270,597],{},[595,1272,600],{},[595,1274,603],{},[605,1276,1277],{},[592,1278,1279,1284,1288],{},[610,1280,1281],{},[389,1282,1283],{},"onCoordinateChanged",[610,1285,1286],{},[389,1287,995],{},[610,1289,1290],{},"The client's camera coordinate changes.",[428,1292,1294],{"id":1293},"choosing-the-right-hook","Choosing the right hook",[375,1296,1297,1298,545,1300,552,1302,1305,1306,545,1308,1310],{},"Use lifecycle events such as ",[389,1299,725],{},[389,1301,737],{},[389,1303,1304],{},"ui.setup"," for initialization that needs engine systems to exist. Use ",[389,1307,883],{},[389,1309,898],{},", and entity tile events for authoritative server gameplay. Use map, camera, and game tick events for client presentation and UI updates.",[375,1312,1313,1314,1316,1317,1319,1320,516],{},"If an action needs data from the other side, combine an event with the network API. For example, a client ",[389,1315,1304],{}," callback can register HUD widgets, while server ",[389,1318,883],{}," can send the initial HUD state with ",[389,1321,148],{},[1323,1324,1325],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":387,"searchDepth":401,"depth":401,"links":1327},[1328,1329,1330,1333,1338,1344],{"id":430,"depth":401,"text":431},{"id":494,"depth":401,"text":495},{"id":528,"depth":401,"text":529,"children":1331},[1332],{"id":536,"depth":408,"text":110},{"id":647,"depth":401,"text":648,"children":1334},[1335,1336,1337],{"id":654,"depth":408,"text":160},{"id":748,"depth":408,"text":152},{"id":913,"depth":408,"text":140},{"id":1025,"depth":401,"text":1026,"children":1339},[1340,1341,1342,1343],{"id":1032,"depth":408,"text":205},{"id":1099,"depth":408,"text":180},{"id":1158,"depth":408,"text":144},{"id":1232,"depth":408,"text":173},{"id":1293,"depth":401,"text":1294},"Register Lua callbacks for Selene bundle events and understand the common, server, and client events currently exposed by the engine.","md",{},{"title":47,"description":1345},"octBhTIswvzvLSBVdcot3TQi3grr02KWqnxLDpsxncc",[1351,1353],{"title":43,"path":44,"stem":45,"description":1352,"children":-1},"Learn how to define client visual entries in Selene bundles and reference them from tiles, entities, and Lua code.",{"title":51,"path":52,"stem":53,"description":1354,"children":-1},"Learn how to create, structure, and package bundles for the Selene engine using the example bundles in this repository.",1792747966453]