feat: add advanced wired variable system and tooling

This commit is contained in:
Lorenzune
2026-04-02 04:44:04 +02:00
parent a43fa87f4c
commit 9dc77aebf7
99 changed files with 22169 additions and 204 deletions
+781
View File
@@ -0,0 +1,781 @@
# Emulator Settings Reference
## Scope
This document inventories the non-wired keys currently stored in `emulator_settings` based on `Default Database/FullDB.sql`. Wired-specific keys are documented separately in `docs/wired_tools_reference.md`.
Each entry below mirrors the comment written by `Database Updates/003_add_comment_column_to_emulator_settings.sql`, so the documentation and in-database comments stay aligned.
## Table schema
```sql
CREATE TABLE `emulator_settings` (
`key` varchar(100) NOT NULL,
`value` varchar(512) NOT NULL,
`comment` text NOT NULL,
PRIMARY KEY (`key`)
);
```
## Inventory summary
- Total non-wired keys documented here: `329`
- Source of defaults: `Default Database/FullDB.sql`
- Value type is inferred from the default string stored in SQL.
## Group index
- `allowed` (1)
- `apollyon` (1)
- `basejump` (2)
- `bots` (1)
- `bubblealerts` (6)
- `bundle` (2)
- `callback` (3)
- `camera` (11)
- `catalog` (5)
- `commands` (3)
- `console` (1)
- `custom` (1)
- `db` (4)
- `debug` (7)
- `discount` (5)
- `easter_eggs` (1)
- `enc` (4)
- `essentials` (2)
- `flood` (1)
- `ftp` (4)
- `furniture` (1)
- `gamecenter` (16)
- `gamedata` (1)
- `guardians` (5)
- `hotel` (169)
- `hotelview` (5)
- `imager` (6)
- `images` (2)
- `info` (1)
- `invisible` (1)
- `io` (3)
- `logging` (6)
- `marketplace` (1)
- `monsterplant` (2)
- `moodlight` (1)
- `navigator` (1)
- `networking` (1)
- `notify` (1)
- `path` (1)
- `pathfinder` (4)
- `pirate_parrot` (2)
- `postit` (1)
- `pyramids` (1)
- `retro` (1)
- `room` (4)
- `rosie` (2)
- `runtime` (1)
- `save` (2)
- `scripter` (1)
- `seasonal` (7)
- `subscriptions` (12)
- `team` (1)
- `youtube` (1)
## `allowed`
Validation rules for usernames and account-facing inputs.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `allowed.username.characters` | `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=!?@:,.` | `list` | Characters allowed when users choose or change a username. |
## `apollyon`
Custom project-specific behaviour switches.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `apollyon.cooldown.amount` | `250` | `integer` | Cooldown in milliseconds used by the Apollyon-specific behaviour or command flow. |
## `basejump`
BaseJump or FastFood launcher URLs.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `basejump.assets.url` | `http://localhost/gamecenter/gamecenter_basejump/BasicAssets.swf` | `url` | Asset URL used by the BaseJump or FastFood game client. |
| `basejump.url` | `http://localhost/game/BaseJump.swf` | `url` | SWF URL used to launch the BaseJump or FastFood game client. |
## `bots`
Miscellaneous visitor-bot display settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `bots.visitor.dateformat` | `yyyy-mm-dd HH:mm` | `string` | Date format used by visitor bots when they print timestamps. |
## `bubblealerts`
Bubble notification behaviour and assets.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `bubblealerts.enabled` | `1` | `boolean` | Master switch for bubble alert notifications. |
| `bubblealerts.notif_friendonline.enabled` | `1` | `boolean` | Enable bubble alerts when friends come online. |
| `bubblealerts.notif_friendonline.image` | `${image.library.url}notifications/figure?p=%figure%` | `template` | Image template used when showing friend-online bubble alerts. |
| `bubblealerts.notif_friendonline.useimage` | `1` | `boolean` | Use the configured figure image inside friend-online bubble alerts. |
| `bubblealerts.notif_marketplace.enabled` | `1` | `boolean` | Show bubble alerts for marketplace notifications. |
| `bubblealerts.notif_purchase.limited` | `0` | `boolean` | Show bubble alerts for limited-item purchases. |
## `bundle`
Bundle-specific toggles for pets and bots.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `bundle.bots.enabled` | `1` | `boolean` | Allow bots to be included in room bundles or package rewards. |
| `bundle.pets.enabled` | `1` | `boolean` | Allow pets to be included in room bundles or package rewards. |
## `callback`
HTTP callback integrations for external services.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `callback.get.version` | `1` | `boolean` | Enable the GET callback used to report version to external services. |
| `callback.post.errors` | `1` | `boolean` | Enable the POST callback used to report errors to external services. |
| `callback.post.statistics` | `1` | `boolean` | Enable the POST callback used to report statistics to external services. |
## `camera`
Camera costs, storage and publish settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `camera.enabled` | `1` | `boolean` | Enable the in-room camera feature. |
| `camera.extradata` | `{\"t\":%timestamp%, \"u\":\"%id%\", \"s\":%room_id%, \"w\":\"%url%\"}` | `template` | Extradata template written into camera photo items when they are created. |
| `camera.item_id` | `45970` | `integer` | Base item ID used by the generated camera photo furniture. |
| `camera.price.credits` | `2` | `integer` | Credit price charged when taking a camera photo. |
| `camera.price.points` | `0` | `boolean` | Amount of activity points charged when taking a camera photo. |
| `camera.price.points.publish` | `10` | `integer` | Amount of activity points charged when publishing a camera photo. |
| `camera.price.points.publish.type` | `0` | `boolean` | Activity point type used for the camera publish cost. |
| `camera.price.points.type` | `0` | `boolean` | Activity point type used for the camera capture cost. |
| `camera.publish.delay` | `180` | `integer` | Delay in seconds before a published camera photo becomes available. |
| `camera.url` | `http://localhost/usercontent/camera/` | `url` | Base URL where camera images are published. |
| `camera.use.https` | `1` | `boolean` | Force HTTPS when generating camera image URLs. |
## `catalog`
Catalog behaviour that is not wired-specific.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `catalog.guild.hc_required` | `1` | `boolean` | Require HC or VIP status before users can create a guild. |
| `catalog.guild.price` | `10` | `integer` | Credit cost required to create a guild. |
| `catalog.ltd.page.soldout` | `761` | `integer` | Layout or image ID used when a limited page is sold out. |
| `catalog.ltd.random` | `1` | `boolean` | Randomize the order or selection of limited catalog items. |
| `catalog.page.vipgifts` | `0` | `boolean` | Catalog page ID used for VIP gift redemption. |
## `commands`
Command-specific restrictions and compatibility flags.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `commands.cmd_chatcolor.banned_numbers` | `23;33;34` | `list` | Semicolon-separated list of chat color IDs blocked for the chatcolor command. |
| `commands.cmd_staffonline.min_rank` | `2` | `integer` | Minimum permission rank required to use the staffonline command. |
| `commands.plugins.oldstyle` | `0` | `boolean` | Use the legacy command plugin loading style. |
## `console`
Console behaviour.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `console.mode` | `1` | `boolean` | Controls the emulator console mode or console output style. |
## `custom`
Fork-specific custom behaviour switches.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `custom.stacking.enabled` | `0` | `boolean` | Enable custom item stacking behaviour outside the default stacking rules. |
## `db`
Database pooling and batching controls.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `db.max.partition.size` | `2` | `integer` | Maximum batch or partition size used by partitioned database operations. |
| `db.min.partition.size` | `1` | `boolean` | Minimum batch or partition size used by partitioned database operations. |
| `db.pool.maxsize` | `12` | `integer` | Maximum size of the database connection pool. |
| `db.pool.minsize` | `8` | `integer` | Minimum number of open connections kept in the database pool. |
## `debug`
Verbose debug output toggles.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `debug.mode` | `1` | `boolean` | Enable general emulator debug mode. |
| `debug.show.errors` | `1` | `boolean` | Show internal debug error messages. |
| `debug.show.headers` | `0` | `boolean` | Show packet headers in debug logs. |
| `debug.show.packets` | `0` | `boolean` | Print packet-level debug output. |
| `debug.show.packets.undefined` | `0` | `boolean` | Print debug output for undefined incoming or outgoing packets. |
| `debug.show.sql.exception` | `1` | `boolean` | Log SQL exceptions to the console. |
| `debug.show.users` | `1` | `boolean` | Show user-related debug messages. |
## `discount`
Discount batch rules for catalog purchases.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `discount.additional.thresholds` | `40;99` | `list` | Semicolon-separated discount thresholds used for extra batch bonuses. |
| `discount.batch.free.items` | `1` | `boolean` | Number of free items granted inside one discount batch. |
| `discount.batch.size` | `6` | `integer` | Number of items required for one discount batch. |
| `discount.bonus.min.discounts` | `1` | `boolean` | Minimum number of discount batches required before the bonus logic applies. |
| `discount.max.allowed.items` | `100` | `integer` | Maximum number of catalog items that can participate in one discount batch. |
## `easter_eggs`
Optional easter egg features.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `easter_eggs.enabled` | `1` | `boolean` | Enable or disable the feature controlled by `easter_eggs.enabled`. |
## `enc`
Encryption and RSA settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `enc.d` | `` | `string` | RSA private exponent used by the encryption layer. |
| `enc.e` | `` | `string` | RSA public exponent used by the encryption layer. |
| `enc.enabled` | `1` | `boolean` | Enable RSA encryption support for the socket handshake. |
| `enc.n` | `` | `string` | RSA modulus used by the encryption layer. |
## `essentials`
Essentials plugin or command values.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `essentials.cmd_kill.effect.killer` | `164;182` | `list` | Semicolon-separated effect IDs used by the kill command for the killer. |
| `essentials.cmd_kill.effect.victim` | `93;89` | `list` | Semicolon-separated effect IDs used by the kill command for the victim. |
## `flood`
Flood-control compatibility switches.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `flood.with.rights` | `0` | `boolean` | Allow users with room rights to bypass the normal flood protection. |
## `ftp`
FTP integration settings for generated assets.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `ftp.enabled` | `0` | `boolean` | Enable FTP uploads for generated assets. |
| `ftp.host` | `example.com` | `string` | FTP host used for asset uploads. |
| `ftp.password` | `password123` | `string` | FTP password used for asset uploads. |
| `ftp.user` | `root` | `string` | FTP username used for asset uploads. |
## `furniture`
General furniture interaction behaviour.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `furniture.talking.range` | `2` | `integer` | Maximum tile distance at which talking furniture can react to nearby speech. |
## `gamecenter`
Gamecenter launchers and theme settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `gamecenter.fastfood.apiKey` | `` | `string` | API key used by the FastFood or BaseJump integration. |
| `gamecenter.fastfood.assets` | `http://localhost/swf/c_images/gamecenter_basejump/` | `url` | Asset base URL used by the FastFood or BaseJump game client. |
| `gamecenter.fastfood.background.color` | `68bbd2` | `string` | Background color used by the FastFood launcher UI. |
| `gamecenter.fastfood.enabled` | `true` | `boolean` | Enable the FastFood or BaseJump gamecenter integration. |
| `gamecenter.fastfood.text.color` | `ffffff` | `string` | Text color used by the FastFood launcher UI. |
| `gamecenter.fastfood.theme` | `default` | `string` | Theme name used by the FastFood launcher. |
| `gamecenter.snowwar.artic.bg` | `http://localhost/swf/c_images/gamecenter_snowwar/snst_bg_1_a_big.png` | `url` | Background image used for the SnowWar Arctic map. |
| `gamecenter.snowwar.assets` | `http://localhost/swf/c_images/gamecenter_snowwar/` | `url` | Asset base URL used by the SnowWar game client. |
| `gamecenter.snowwar.dragoncave.bg` | `http://localhost/swf/c_images/gamecenter_snowwar/snst_bg_2_big.png` | `url` | Background image used for the SnowWar Dragon Cave map. |
| `gamecenter.snowwar.enabled` | `true` | `boolean` | Enable the SnowWar gamecenter integration. |
| `gamecenter.snowwar.fightnight.bg` | `http://localhost/swf/c_images/gamecenter_snowwar/snst_bg_3_noscale.png` | `url` | Background image used for the SnowWar Fight Night map. |
| `gamecenter.snowwar.game.background.color` | `93d4f3` | `string` | Background color used by the SnowWar launcher UI. |
| `gamecenter.snowwar.game.start.time` | `15` | `integer` | Countdown in seconds before a SnowWar round starts. |
| `gamecenter.snowwar.game.text.color` | `000000` | `integer` | Text color used by the SnowWar launcher UI. |
| `gamecenter.snowwar.players.min` | `2` | `integer` | Minimum number of players required to start SnowWar. |
| `gamecenter.snowwar.room.id` | `0` | `boolean` | Room ID used as the SnowWar lobby or host room. |
## `gamedata`
Remote gamedata sources.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `gamedata.figuredata.url` | `https://habbo.com/gamedata/figuredata/0` | `url` | Remote figuredata URL used when the hotel loads avatar figure definitions. |
## `guardians`
Guardians and report-review settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `guardians.accept.timer` | `90` | `integer` | Time in seconds that guardians have to accept a case. |
| `guardians.maximum.guardians.total` | `10` | `integer` | Maximum number of guardians that can be assigned to one case. |
| `guardians.maximum.resends` | `2` | `integer` | Maximum number of times an unanswered guardian case can be resent. |
| `guardians.minimum.votes` | `5` | `integer` | Minimum number of guardian votes required to resolve a case. |
| `guardians.reporting.cooldown` | `900` | `integer` | Cooldown in seconds before the same user can open a new guardian report. |
## `hotel`
Core hotel gameplay, economy, room, catalog and moderation settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `hotel.alert.oldstyle` | `0` | `boolean` | Use the legacy generic alert window style. |
| `hotel.allow.ignore.staffs` | `1` | `boolean` | Allow users to ignore staff accounts. |
| `hotel.auto.credits.amount` | `100` | `integer` | Amount of credits granted on each automatic payout. |
| `hotel.auto.credits.enabled` | `1` | `boolean` | Enable automatic credits payouts. |
| `hotel.auto.credits.hc_modifier` | `1` | `boolean` | Multiplier applied to automatic credits payouts for HC users. |
| `hotel.auto.credits.ignore.hotelview` | `1` | `boolean` | Skip users staying in hotel view when giving automatic credits payouts. |
| `hotel.auto.credits.ignore.idled` | `0` | `boolean` | Skip idle users when giving automatic credits payouts. |
| `hotel.auto.credits.interval` | `600` | `integer` | Interval in seconds between automatic credits payouts. |
| `hotel.auto.gotwpoints.enabled` | `0` | `boolean` | Enable automatic gotwpoints payouts. |
| `hotel.auto.gotwpoints.hc_modifier` | `1` | `boolean` | Multiplier applied to automatic gotwpoints payouts for HC users. |
| `hotel.auto.gotwpoints.ignore.hotelview` | `1` | `boolean` | Skip users staying in hotel view when giving automatic gotwpoints payouts. |
| `hotel.auto.gotwpoints.ignore.idled` | `1` | `boolean` | Skip idle users when giving automatic gotwpoints payouts. |
| `hotel.auto.gotwpoints.interval` | `600` | `integer` | Interval in seconds between automatic gotwpoints payouts. |
| `hotel.auto.gotwpoints.name` | `shell` | `string` | Internal currency name used by the automatic gotwpoints payout. |
| `hotel.auto.gotwpoints.type` | `4` | `integer` | Currency type ID used by the automatic gotwpoints payout. |
| `hotel.auto.pixels.amount` | `100` | `integer` | Amount of pixels granted on each automatic payout. |
| `hotel.auto.pixels.enabled` | `1` | `boolean` | Enable automatic pixels payouts. |
| `hotel.auto.pixels.hc_modifier` | `1` | `boolean` | Multiplier applied to automatic pixels payouts for HC users. |
| `hotel.auto.pixels.ignore.hotelview` | `1` | `boolean` | Skip users staying in hotel view when giving automatic pixels payouts. |
| `hotel.auto.pixels.ignore.idled` | `1` | `boolean` | Skip idle users when giving automatic pixels payouts. |
| `hotel.auto.pixels.interval` | `600` | `integer` | Interval in seconds between automatic pixels payouts. |
| `hotel.auto.points.amount` | `5` | `integer` | Amount of points granted on each automatic payout. |
| `hotel.auto.points.enabled` | `1` | `boolean` | Enable automatic points payouts. |
| `hotel.auto.points.hc_modifier` | `1` | `boolean` | Multiplier applied to automatic points payouts for HC users. |
| `hotel.auto.points.ignore.hotelview` | `0` | `boolean` | Skip users staying in hotel view when giving automatic points payouts. |
| `hotel.auto.points.ignore.idled` | `0` | `boolean` | Skip idle users when giving automatic points payouts. |
| `hotel.auto.points.interval` | `600` | `integer` | Interval in seconds between automatic points payouts. |
| `hotel.banzai.points.tile.fill` | `0` | `boolean` | Configuration value used by `hotel.banzai.points.tile.fill`. |
| `hotel.banzai.points.tile.lock` | `1` | `boolean` | Configuration value used by `hotel.banzai.points.tile.lock`. |
| `hotel.banzai.points.tile.steal` | `0` | `boolean` | Configuration value used by `hotel.banzai.points.tile.steal`. |
| `hotel.bot.butler.commanddistance` | `5` | `integer` | Maximum tile distance from which a butler bot accepts commands. |
| `hotel.bot.butler.servedistance` | `5` | `integer` | Maximum tile distance from which a butler bot can serve requests. |
| `hotel.bot.chat.minimum.interval` | `5` | `integer` | Minimum number of seconds between bot chat lines. |
| `hotel.bot.max.chatdelay` | `604800` | `integer` | Maximum bot chat delay allowed when configuring scripted speech. |
| `hotel.bot.max.chatlength` | `120` | `integer` | Maximum number of characters allowed in bot chat lines. |
| `hotel.bot.max.namelength` | `15` | `integer` | Maximum number of characters allowed in bot names. |
| `hotel.bots.max.inventory` | `25` | `integer` | Maximum number of bots allowed in one inventory. |
| `hotel.bots.max.room` | `10` | `integer` | Maximum number of bots allowed in one room. |
| `hotel.calendar.default` | `test` | `string` | Default calendar campaign name or identifier. |
| `hotel.calendar.enabled` | `0` | `boolean` | Enable the hotel calendar feature. |
| `hotel.calendar.pixels.hc_modifier` | `2.0` | `number` | Multiplier applied to calendar pixel rewards for HC users. |
| `hotel.calendar.starttimestamp` | `1593561600` | `integer` | Unix timestamp used as the calendar start date. |
| `hotel.catalog.discounts.amount` | `6` | `integer` | Number of discount slots or discount batches shown by the catalog. |
| `hotel.catalog.items.display.ordernum` | `1` | `boolean` | Respect catalog item order numbers when rendering pages. |
| `hotel.catalog.ltd.limit.enabled` | `1` | `boolean` | Enable daily purchase limits for limited catalog items. |
| `hotel.catalog.purchase.cooldown` | `1` | `boolean` | Cooldown in seconds between catalog purchases. |
| `hotel.catalog.recycler.enabled` | `1` | `boolean` | Enable the catalog recycler feature. |
| `hotel.chat.max.length` | `100` | `integer` | Maximum number of characters allowed in one public chat message. |
| `hotel.daily.respect` | `3` | `integer` | Daily amount of respect points available for users. |
| `hotel.daily.respect.pets` | `3` | `integer` | Daily amount of pet respect points available for users. |
| `hotel.ecotron.enabled` | `1` | `boolean` | Enable or disable the feature controlled by `hotel.ecotron.enabled`. |
| `hotel.ecotron.rarity.chance.1` | `1` | `boolean` | Configuration value used by `hotel.ecotron.rarity.chance.1`. |
| `hotel.ecotron.rarity.chance.2` | `4` | `integer` | Configuration value used by `hotel.ecotron.rarity.chance.2`. |
| `hotel.ecotron.rarity.chance.3` | `40` | `integer` | Configuration value used by `hotel.ecotron.rarity.chance.3`. |
| `hotel.ecotron.rarity.chance.4` | `200` | `integer` | Configuration value used by `hotel.ecotron.rarity.chance.4`. |
| `hotel.ecotron.rarity.chance.5` | `2000` | `integer` | Configuration value used by `hotel.ecotron.rarity.chance.5`. |
| `hotel.flood.mute.time` | `30` | `integer` | Mute duration in seconds applied by the hotel flood protection. |
| `hotel.floorplan.max.totalarea` | `4096` | `integer` | Maximum total floorplan area allowed for custom rooms. |
| `hotel.floorplan.max.widthlength` | `64` | `integer` | Maximum floorplan width or length allowed for custom rooms. |
| `hotel.freeze.onfreeze.loose.explosionboost` | `3` | `integer` | Number of explosion boosts lost when a player gets frozen. |
| `hotel.freeze.onfreeze.loose.snowballs` | `5` | `integer` | Number of snowballs lost when a player gets frozen. |
| `hotel.freeze.onfreeze.time.frozen` | `5` | `integer` | Time in seconds a player remains frozen. |
| `hotel.freeze.points.block` | `1` | `boolean` | Score awarded for blocking tiles in Freeze. |
| `hotel.freeze.points.effect` | `3` | `integer` | Score awarded for using Freeze effects or power-up actions. |
| `hotel.freeze.points.freeze` | `10` | `integer` | Score awarded for freezing another player in Freeze. |
| `hotel.freeze.powerup.chance` | `33` | `integer` | Chance for Freeze power-ups to spawn. |
| `hotel.freeze.powerup.max.lives` | `3` | `integer` | Maximum number of extra lives granted by a Freeze power-up. |
| `hotel.freeze.powerup.max.snowballs` | `5` | `integer` | Maximum number of extra snowballs granted by a Freeze power-up. |
| `hotel.freeze.powerup.protection.stack` | `1` | `boolean` | Allow Freeze protection power-ups to stack. |
| `hotel.freeze.powerup.protection.time` | `10` | `integer` | Protection time in seconds after receiving a Freeze protection power-up. |
| `hotel.friendcategory` | `0` | `boolean` | Default friend category ID assigned to new friends. |
| `hotel.furni.gym.achievement.olympics_c16_crosstrainer` | `CrossTrainer` | `string` | Configuration value used by `hotel.furni.gym.achievement.olympics_c16_crosstrainer`. |
| `hotel.furni.gym.achievement.olympics_c16_trampoline` | `Trampolinist` | `string` | Configuration value used by `hotel.furni.gym.achievement.olympics_c16_trampoline`. |
| `hotel.furni.gym.achievement.olympics_c16_treadmill` | `Jogger` | `string` | Configuration value used by `hotel.furni.gym.achievement.olympics_c16_treadmill`. |
| `hotel.furni.gym.forcerot.olympics_c16_crosstrainer` | `1` | `boolean` | Configuration value used by `hotel.furni.gym.forcerot.olympics_c16_crosstrainer`. |
| `hotel.furni.gym.forcerot.olympics_c16_trampoline` | `0` | `boolean` | Configuration value used by `hotel.furni.gym.forcerot.olympics_c16_trampoline`. |
| `hotel.furni.gym.forcerot.olympics_c16_treadmill` | `1` | `boolean` | Configuration value used by `hotel.furni.gym.forcerot.olympics_c16_treadmill`. |
| `hotel.gifts.box_types` | `0,1,2,3,4,5,6,8` | `list` | Comma-separated list of gift box type IDs allowed in the catalog. |
| `hotel.gifts.length.max` | `300` | `integer` | Maximum message length allowed on gift notes. |
| `hotel.gifts.ribbon_types` | `0,1,2,3,4,5,6,7,8,9,10` | `list` | Comma-separated list of ribbon type IDs allowed in the catalog. |
| `hotel.gifts.special.price` | `10` | `integer` | Credit price used by special gift boxes. |
| `hotel.home.room` | `0` | `boolean` | Room ID used as the default home room for new users. |
| `hotel.inventory.max.items` | `7500` | `integer` | Maximum number of items allowed in one inventory. |
| `hotel.item.trap.hween14_rare2` | `3000` | `integer` | Configuration value used by `hotel.item.trap.hween14_rare2`. |
| `hotel.item.trap.hween_c17_handstrap` | `3000` | `integer` | Configuration value used by `hotel.item.trap.hween_c17_handstrap`. |
| `hotel.item.trap.hween_c17_spiketrap` | `3000` | `integer` | Configuration value used by `hotel.item.trap.hween_c17_spiketrap`. |
| `hotel.item.trap.pirate_sandtrap` | `3000` | `integer` | Configuration value used by `hotel.item.trap.pirate_sandtrap`. |
| `hotel.jukebox.limit.large` | `20` | `integer` | Track limit used by large jukebox furniture. |
| `hotel.jukebox.limit.normal` | `10` | `integer` | Track limit used by normal jukebox furniture. |
| `hotel.log.chat` | `1` | `boolean` | Enable logging for chat. |
| `hotel.log.chat.private` | `1` | `boolean` | Enable logging for chat private. |
| `hotel.log.room.enter` | `1` | `boolean` | Enable logging for room enter. |
| `hotel.log.trades` | `1` | `boolean` | Enable logging for trades. |
| `hotel.marketplace.currency` | `0` | `boolean` | Currency type used for marketplace prices and taxes. |
| `hotel.marketplace.enabled` | `1` | `boolean` | Enable or disable the feature controlled by `hotel.marketplace.enabled`. |
| `hotel.max.bots.room` | `10` | `integer` | Maximum number of bots allowed in one room. |
| `hotel.max.duckets` | `9000000` | `integer` | Maximum amount of duckets a user can hold. |
| `hotel.messenger.offline.messaging.enabled` | `1` | `boolean` | Enable or disable the feature controlled by `hotel.messenger.offline.messaging.enabled`. |
| `hotel.messenger.search.maxresults` | `50` | `integer` | Maximum number of results returned by messenger user searches. |
| `hotel.name` | `Habbo Hotel` | `string` | Public hotel name shown across the client and outgoing messages. |
| `hotel.navigator.camera` | `1` | `boolean` | Enable navigator room previews or camera mode. |
| `hotel.navigator.owner` | `HabboHotel` | `string` | Default owner name displayed by the navigator. |
| `hotel.navigator.popular.amount` | `35` | `integer` | Number of rooms shown in the popular rooms list. |
| `hotel.navigator.popular.category.maxresults` | `10` | `integer` | Maximum number of rooms shown per popular category. |
| `hotel.navigator.popular.listtype` | `1` | `boolean` | List type used for the popular rooms tab. |
| `hotel.navigator.populartab.publics` | `0` | `boolean` | Include public rooms inside the popular rooms tab. |
| `hotel.navigator.search.maxresults` | `35` | `integer` | Maximum number of results returned by navigator searches. |
| `hotel.navigator.sort.ordernum` | `1` | `boolean` | Respect order numbers when sorting navigator results. |
| `hotel.navigator.staffpicks.categoryid` | `1` | `boolean` | Category ID used for the staff picks tab. |
| `hotel.nux.gifts.enabled` | `0` | `boolean` | Enable the NUX gift flow for new users. |
| `hotel.pets.max.inventory` | `25` | `integer` | Maximum number of pets allowed in one inventory. |
| `hotel.pets.max.room` | `10` | `integer` | Maximum number of pets allowed in one room. |
| `hotel.pets.name.length.max` | `15` | `integer` | Maximum pet name length. |
| `hotel.pets.name.length.min` | `3` | `integer` | Minimum pet name length. |
| `hotel.player.name` | `Habbo` | `string` | Generic player label used by text templates and client messages. |
| `hotel.purchase.ltd.limit.daily.item` | `3` | `integer` | Maximum number of the same limited item a user can buy per day. |
| `hotel.purchase.ltd.limit.daily.total` | `10` | `integer` | Maximum number of limited items a user can buy per day across all limited sales. |
| `hotel.refill.daily` | `86400` | `integer` | Cooldown in seconds before daily counters such as respect are refilled. |
| `hotel.rollers.speed.maximum` | `100` | `integer` | Maximum roller delay or speed value accepted by roller furniture. |
| `hotel.room.enter.logs` | `1` | `boolean` | Enable room-entry logs. |
| `hotel.room.floorplan.check.enabled` | `1` | `boolean` | Validate custom floorplans before rooms are saved. |
| `hotel.room.furni.max` | `2500` | `integer` | Maximum amount of furniture allowed in one room. |
| `hotel.room.nooblobby` | `3` | `integer` | Room ID used as the newbie lobby. |
| `hotel.room.public.doortile.kick` | `0` | `boolean` | Kick users who stand on public room door tiles. |
| `hotel.room.rollers.norules` | `0` | `boolean` | Allow rollers to ignore normal placement rules. |
| `hotel.room.rollers.roll_avatars.max` | `1` | `boolean` | Maximum number of avatars that rollers can move at once. |
| `hotel.room.stickies.max` | `200` | `integer` | Maximum number of sticky notes allowed in one room. |
| `hotel.room.stickypole.prefix` | `%timestamp%, %username%:\\r` | `template` | Prefix template written by sticky pole furniture. |
| `hotel.room.tags.staff` | `staff;official;habbo` | `list` | Semicolon-separated staff room tags. |
| `hotel.rooms.auto.idle` | `1` | `boolean` | Allow empty rooms to switch into the idle state automatically. |
| `hotel.rooms.deco_hosting` | `1` | `boolean` | Enable decoration-hosting features for rooms. |
| `hotel.rooms.handitem.time` | `100` | `integer` | Time in seconds before temporary hand items are cleared. |
| `hotel.rooms.max.favorite` | `30` | `integer` | Maximum number of favorite rooms allowed per user. |
| `hotel.roomuser.idle.cycles` | `300` | `integer` | Idle cycle count before a room user is marked idle. |
| `hotel.roomuser.idle.cycles.kick` | `900` | `integer` | Idle cycle count before a room user is kicked for idling. |
| `hotel.roomuser.idle.not_dancing.ignore.wired_idle` | `0` | `boolean` | Ignore the wired idle status when checking the room idle rule. |
| `hotel.sanctions.enabled` | `1` | `boolean` | Enable the sanctions system. |
| `hotel.shop.discount.modifier` | `6` | `integer` | Modifier used by the shop discount calculation. |
| `hotel.talenttrack.enabled` | `1` | `boolean` | Enable the talent track feature. |
| `hotel.targetoffer.id` | `1` | `boolean` | Offer ID requested when the client asks for a targeted offer. |
| `hotel.teleport.locked.allowed` | `1` | `boolean` | Allow users to use teleports inside locked rooms when they otherwise qualify. |
| `hotel.trading.enabled` | `1` | `boolean` | Enable room trading. |
| `hotel.trading.requires.perk` | `0` | `boolean` | Require the trading perk before users may trade. |
| `hotel.trophies.length.max` | `300` | `integer` | Maximum value used by `hotel.trophies.length.max`. |
| `hotel.users.clothingvalidation.onchangelooks` | `0` | `boolean` | Run clothing validation when the related action occurs: onchangelooks. |
| `hotel.users.clothingvalidation.onfballgate` | `0` | `boolean` | Run clothing validation when the related action occurs: onfballgate. |
| `hotel.users.clothingvalidation.onhcexpired` | `0` | `boolean` | Run clothing validation when the related action occurs: onhcexpired. |
| `hotel.users.clothingvalidation.onlogin` | `0` | `boolean` | Run clothing validation when the related action occurs: onlogin. |
| `hotel.users.clothingvalidation.onmannequin` | `0` | `boolean` | Run clothing validation when the related action occurs: onmannequin. |
| `hotel.users.clothingvalidation.onmimic` | `0` | `boolean` | Run clothing validation when the related action occurs: onmimic. |
| `hotel.users.max.friends` | `300` | `integer` | Maximum number of friends allowed for normal users. |
| `hotel.users.max.friends.hc` | `1100` | `integer` | Maximum number of friends allowed for HC users. |
| `hotel.users.max.rooms` | `50` | `integer` | Maximum number of rooms allowed for normal users. |
| `hotel.users.max.rooms.hc` | `75` | `integer` | Maximum number of rooms allowed for HC users. |
| `hotel.view.ltdcountdown.enabled` | `1` | `boolean` | Enable the limited-countdown hotel-view widget. |
| `hotel.view.ltdcountdown.itemid` | `10388` | `integer` | Item ID shown by the limited-countdown widget. |
| `hotel.view.ltdcountdown.itemname` | `trophy_netsafety_0` | `string` | Item name shown by the limited-countdown widget. |
| `hotel.view.ltdcountdown.pageid` | `13` | `integer` | Catalog page ID linked by the limited-countdown widget. |
| `hotel.view.ltdcountdown.timestamp` | `1519496132` | `integer` | Unix timestamp used by the limited-countdown widget. |
| `hotel.welcome.alert.delay` | `10000` | `integer` | Delay in milliseconds before the welcome alert is shown. |
| `hotel.welcome.alert.enabled` | `0` | `boolean` | Enable the welcome alert shown after login. |
| `hotel.welcome.alert.message` | `Welcome to Habbo Hotel %user%!` | `template` | Message template used by the welcome alert. |
| `hotel.welcome.alert.oldstyle` | `0` | `boolean` | Use the legacy welcome alert window style. |
| `hotel.wordfilter.automute` | `1` | `boolean` | Mute duration in minutes applied when word-filter automute is triggered. |
| `hotel.wordfilter.enabled` | `1` | `boolean` | Enable the word filter system. |
| `hotel.wordfilter.messenger` | `1` | `boolean` | Apply the word filter to messenger messages. |
| `hotel.wordfilter.normalise` | `1` | `boolean` | Normalise text before checking it against the word filter. |
| `hotel.wordfilter.replacement` | `bobba` | `string` | Replacement word used when text is censored. |
| `hotel.wordfilter.rooms` | `1` | `boolean` | Apply the word filter to room chat. |
## `hotelview`
Hotel-view widgets and promotional data.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `hotelview.halloffame.query` | `SELECT users.look, users.username, users.id, users_settings.hof_points FROM users_settings INNER JOIN users ON users_settings.user_id = users.id WHERE hof_points > 0 ORDER BY hof_points DESC, users.id ASC LIMIT 10` | `sql` | SQL query used to populate the hotel-view hall of fame panel. |
| `hotelview.promotional.points` | `100` | `integer` | Amount of activity points awarded by the hotel-view promotion. |
| `hotelview.promotional.points.type` | `5` | `integer` | Activity point type used by the hotel-view promotional reward. |
| `hotelview.promotional.reward.id` | `11043` | `integer` | Base item ID used by the hotel-view promotional reward. |
| `hotelview.promotional.reward.name` | `bonusbag20_2` | `string` | Public item name used by the hotel-view promotional reward. |
## `imager`
Internal image generator paths and URLs.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `imager.internal.enabled` | `1` | `boolean` | Generate images locally instead of relying on an external imager service. |
| `imager.location.badgeparts` | `/var/www/testhotel/Cosmic/public/usercontent/badgeparts` | `string` | Filesystem path where badge part assets are stored. |
| `imager.location.output.badges` | `/var/www/testhotel/Cosmic/public/usercontent/badgeparts/generated/` | `string` | Filesystem output path for generated badges. |
| `imager.location.output.camera` | `/var/www/testhotel/Cosmic/public/usercontent/camera/` | `string` | Filesystem output path for saved camera photos. |
| `imager.location.output.thumbnail` | `/var/www/testhotel/Cosmic/public/usercontent/camera/thumbnail/` | `string` | Filesystem output path for generated camera thumbnails. |
| `imager.url.youtube` | `imager.php?url=http://img.youtube.com/vi/%video%/default.jpg` | `template` | Template URL used to fetch YouTube thumbnails. |
## `images`
Static client image path helpers.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `images.gamecenter.basejump` | `c_images/gamecenter_basejump/` | `string` | Client asset path used for the basejump gamecenter images. |
| `images.gamecenter.snowwar` | `c_images/gamecenter_snowwar/` | `string` | Client asset path used for the snowwar gamecenter images. |
## `info`
Global information panel toggle.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `info.shown` | `1` | `boolean` | Show the hotel information panel or startup information message. |
## `invisible`
Invisible-mode behaviour.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `invisible.prevent.chat` | `0` | `boolean` | Prevent invisible users from speaking in rooms. |
## `io`
Socket and Netty threading settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `io.bossgroup.threads` | `1` | `boolean` | Number of Netty boss-group threads used by the socket server. |
| `io.client.multithreaded.handler` | `1` | `boolean` | Handle incoming client packets with a multi-threaded pipeline. |
| `io.workergroup.threads` | `5` | `integer` | Number of Netty worker-group threads used by the socket server. |
## `logging`
Structured emulator logging toggles.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `logging.debug` | `0` | `boolean` | Enable extra debug logging in the emulator logger. |
| `logging.errors.packets` | `0` | `boolean` | Log packet parsing errors. |
| `logging.errors.runtime` | `1` | `boolean` | Log runtime exceptions. |
| `logging.errors.sql` | `1` | `boolean` | Log SQL errors. |
| `logging.packets` | `0` | `boolean` | Log packet traffic in the standard logger. |
| `logging.packets.undefined` | `0` | `boolean` | Log undefined packets in the standard logger. |
## `marketplace`
Marketplace compatibility flag.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `marketplace.enabled` | `1` | `boolean` | Global switch for the marketplace subsystem. |
## `monsterplant`
Monster plant seed item mapping.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `monsterplant.seed.item_id` | `4582` | `integer` | Configuration value used by `monsterplant.seed.item_id`. |
| `monsterplant.seed_rare.item_id` | `4604` | `integer` | Configuration value used by `monsterplant.seed_rare.item_id`. |
## `moodlight`
Moodlight validation switches.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `moodlight.color_check.enabled` | `1` | `boolean` | Validate moodlight color values before applying them. |
## `navigator`
Navigator static definitions.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `navigator.eventcategories` | `1,Hottest Events,false;2,Parties & Music,true;3,Role Play,true;4,Help Desk,true;5,Trading,true;6,Games,true;7,Debates & Discussions,true;8,Grand Openings,true;9,Friending,true;10,Jobs,true;11,Group Events,true` | `list` | Semicolon-separated navigator event category definitions shown in the events tab. |
## `networking`
Low-level networking compatibility switches.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `networking.tcp.proxy` | `0` | `boolean` | Enable TCP proxy-aware networking behaviour. |
## `notify`
Server-side notification automation.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `notify.staff.chat.auto.report` | `1` | `boolean` | Automatically notify staff when a chat report is created. |
## `path`
Asset path helpers.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `path.furniture.icons` | `${image.library.url}/icons/` | `template` | Base path used by the client to load furniture icon assets. |
## `pathfinder`
Pathfinder safety and performance settings.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `pathfinder.execution_time.milli` | `25` | `integer` | Maximum pathfinder execution time in milliseconds before aborting. |
| `pathfinder.max_execution_time.enabled` | `1` | `boolean` | Enforce the pathfinder execution time limit. |
| `pathfinder.step.allow.falling` | `1` | `boolean` | Allow the pathfinder to walk down falling steps. |
| `pathfinder.step.maximum.height` | `1.1` | `number` | Maximum height difference the pathfinder may step onto. |
## `pirate_parrot`
Pirate parrot text and bubble behaviour.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `pirate_parrot.message.bubble` | `28` | `integer` | Chat bubble style ID used by the pirate parrot. |
| `pirate_parrot.message.count` | `6` | `integer` | Number of predefined messages available to the pirate parrot. |
## `postit`
Post-it constraints.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `postit.charlimit` | `366` | `integer` | Maximum number of characters allowed on post-it notes. |
## `pyramids`
Pyramids minigame timing.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `pyramids.max.delay` | `18` | `integer` | Maximum delay allowed in the Pyramids minigame or puzzle timing. |
## `retro`
Retro compatibility switches.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `retro.style.homeroom` | `1` | `boolean` | Use retro-style home room behaviour in the navigator or onboarding flow. |
## `room`
Generic room chat and promotion behaviour.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `room.chat.delay` | `0` | `boolean` | Extra room chat delay applied before users can speak again. |
| `room.chat.mutearea.allow_whisper` | `1` | `boolean` | Allow whispering while a user stands inside a mute area. |
| `room.chat.prefix.format` | `[<font color=\"%color%\">%prefix%</font>] ` | `string` | HTML or text format used for room chat prefixes. |
| `room.promotion.badge` | `RADZZ` | `string` | Badge code displayed on promoted rooms. |
## `rosie`
Rosie-related client notifications and purchase currency.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `rosie.bubble.image.url` | `${image.library.url}notifications/generic.png` | `template` | Image used by Rosie bubble notifications. |
| `rosie.buyroom.currency.type` | `5` | `integer` | Currency type used by Rosie when buying a room or room package. |
## `runtime`
Executor and thread sizing.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `runtime.threads` | `8` | `integer` | Configuration value used by `runtime.threads`. |
## `save`
Chat persistence toggles.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `save.private.chats` | `1` | `boolean` | Configuration value used by `save.private.chats`. |
| `save.room.chats` | `1` | `boolean` | Configuration value used by `save.room.chats`. |
## `scripter`
Scripter or modtool integration.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `scripter.modtool.tickets` | `1` | `boolean` | Expose moderation tickets to the scripter or automation tooling. |
## `seasonal`
Seasonal currency mapping.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `seasonal.currency.diamond` | `5` | `integer` | Currency type ID used for diamonds. |
| `seasonal.currency.ducket` | `0` | `boolean` | Currency type ID used for duckets. |
| `seasonal.currency.names` | `ducket;pixel;shell;diamond` | `list` | Semicolon-separated display names for seasonal currency types. |
| `seasonal.currency.pixel` | `0` | `boolean` | Currency type ID used for pixels. |
| `seasonal.currency.shell` | `4` | `integer` | Currency type ID used for shells. |
| `seasonal.primary.type` | `5` | `integer` | Primary seasonal currency type ID. |
| `seasonal.types` | `0;1;2;3;4;5;101;102;103;104;105` | `list` | Semicolon-separated list of currency type IDs treated as seasonal currencies. |
## `subscriptions`
HC scheduler, payday and discount configuration.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `subscriptions.hc.achievement` | `VipHC` | `string` | Achievement code granted for the HC subscription tier. |
| `subscriptions.hc.discount.days_before_end` | `7` | `integer` | Number of days before expiry when HC discount offers become available. |
| `subscriptions.hc.discount.enabled` | `1` | `boolean` | Enable discounted HC renewal offers. |
| `subscriptions.hc.payday.creditsspent_reset_on_expire` | `1` | `boolean` | Reset tracked credits spent when the HC subscription expires. |
| `subscriptions.hc.payday.currency` | `credits` | `string` | Currency rewarded by the HC payday system. |
| `subscriptions.hc.payday.enabled` | `1` | `boolean` | Enable the HC payday reward system. |
| `subscriptions.hc.payday.interval` | `1 month` | `string` | Date interval used between HC payday reward runs. |
| `subscriptions.hc.payday.next_date` | `2020-10-15 00:00:00` | `string` | Next scheduled execution date for HC payday rewards. |
| `subscriptions.hc.payday.percentage` | `10` | `integer` | Percentage of eligible spending returned by HC payday. |
| `subscriptions.hc.payday.streak` | `7=5;30=10;60=15;90=20;180=25;365=30` | `list` | Semicolon-separated streak thresholds and rewards for HC payday. |
| `subscriptions.scheduler.enabled` | `1` | `boolean` | Enable the subscription background scheduler. |
| `subscriptions.scheduler.interval` | `10` | `integer` | Interval in minutes between subscription scheduler runs. |
## `team`
Compatibility markers for team or wired integrations.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `team.wired.update.rc-1` | `DO NOT REMOVE THIS SETTING!` | `string` | Compatibility marker used by the custom team wired implementation. Do not remove. |
## `youtube`
YouTube integration credentials.
| Key | Default value | Type | Purpose |
|---|---|---|---|
| `youtube.apikey` | `` | `string` | API key used by the YouTube integration. |
+187
View File
@@ -0,0 +1,187 @@
# Permissions schema reference
## Overview
The legacy `permissions` table stores:
- one row per rank
- one column per permission key
That works for runtime, but it becomes very hard to read and maintain once the number of permission keys grows.
The updated design keeps only the rank metadata separated, while the permission matrix itself becomes one readable table:
- `permission_ranks`
- one row per rank
- stores rank metadata such as `rank_name`, `badge`, `level`, `prefix`, `room_effect`, and the automatic currency amounts
- `permission_definitions`
- one row per permission key
- stores the permission comment in the same row
- stores one column per rank using the format `rank_<id>`
Example:
| permission_key | max_value | comment | rank_1 | rank_2 | rank_7 |
| --- | --- | --- | --- | --- | --- |
| `acc_ads_background` | `1` | Allows editing room advertisement backgrounds. | `0` | `0` | `1` |
## Runtime behavior
- The emulator still supports the legacy `permissions` table as a fallback.
- If `permission_ranks` and `permission_definitions` exist and contain data, the emulator loads the new schema instead.
- If the new schema is missing, incomplete, or fails to load, the emulator falls back to the legacy `permissions` table automatically.
Relevant runtime files:
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/permissions/PermissionsManager.java:45`
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/permissions/Rank.java:71`
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/modtool/ModToolManager.java:57`
## Tables
### `permission_ranks`
This table stores only rank metadata:
- `id`
- `rank_name`
- `hidden_rank`
- `badge`
- `job_description`
- `staff_color`
- `staff_background`
- `level`
- `room_effect`
- `log_commands`
- `prefix`
- `prefix_color`
- `auto_credits_amount`
- `auto_pixels_amount`
- `auto_gotw_amount`
- `auto_points_amount`
#### `permission_ranks` field meanings
- `id`
- Numeric rank id used everywhere else in the emulator, including `users.rank` and the dynamic `rank_<id>` columns in `permission_definitions`.
- `rank_name`
- Human-readable name of the rank, such as `User`, `Moderator`, or `Administrator`.
- `hidden_rank`
- When enabled, the rank is treated as hidden in places where staff visibility should be reduced.
- `badge`
- Badge code automatically associated with the rank.
- `job_description`
- Staff/job description text shown in features that expose rank profile details.
- `staff_color`
- Hex color used by staff UI or visuals that depend on the rank color.
- `staff_background`
- Background asset name used for staff visuals tied to the rank.
- `level`
- Priority/order value of the rank; higher values usually mean stronger staff level or broader access.
- `room_effect`
- Default avatar effect id associated with the rank when that feature is used.
- `log_commands`
- Controls whether commands executed by users with this rank should be logged in command logs.
- `prefix`
- Short in-room staff prefix/tag associated with the rank.
- `prefix_color`
- Hex color used for the displayed rank prefix.
- `auto_credits_amount`
- Automatic credit amount granted by rank-based reward/payday style logic, if used by the hotel.
- `auto_pixels_amount`
- Automatic duckets/pixels amount granted by rank-based reward/payday style logic, if used by the hotel.
- `auto_gotw_amount`
- Automatic GOTW-style points amount granted by rank-based reward/payday style logic, if used by the hotel.
- `auto_points_amount`
- Automatic activity-points amount granted by rank-based reward/payday style logic, if used by the hotel.
### `permission_definitions`
This table stores:
- `permission_key`
- `max_value`
- `comment`
- one dynamic column per rank:
- `rank_1`
- `rank_2`
- `rank_3`
- ...
That means the table itself is already the readable matrix you wanted:
- rows = permission keys
- columns = rank values
- comment stays next to the key
## Value semantics
Permission values keep the same meaning as today:
- `0` = disabled
- `1` = allowed
- `2` = allowed only when room-owner rights may be used
The schema stores that information in:
- `permission_definitions.max_value`
## Migration behavior
`Database Updates/004_normalize_permissions_schema.sql` does the following:
1. keeps the legacy `permissions` table untouched
2. creates `permission_ranks`
3. creates `permission_definitions`
4. copies rank metadata from `permissions` into `permission_ranks`
5. creates any missing `rank_<id>` columns in `permission_definitions`
6. creates one row per permission key with `max_value` and a comment
7. applies curated per-key comments so every permission explains what it actually does in code
8. copies each old permission value into the proper `rank_<id>` column
It also removes the older experimental objects if they already exist:
- `permission_rank_values`
- `permission_nodes`
- `permissions_matrix_view`
- `refresh_permissions_matrix_view`
## Adding a new rank later
When you add a new rank after the migration:
1. insert the rank metadata into `permission_ranks`
2. reload permissions with emulator restart or `:update_permissions`
3. the emulator automatically creates the missing `rank_<id>` column in `permission_definitions` if it does not exist yet
4. set the new `rank_<id>` values in `permission_definitions`
You can still run the helper procedure manually if you want to sync the schema before the next reload:
```sql
CALL refresh_permission_definition_rank_columns();
```
If you want to refresh all values again from the old legacy table during rollout, you can also run:
```sql
CALL refresh_permission_definition_values();
```
## Notes about comments and legacy keys
The comments stored in `permission_definitions.comment` are intentionally hand-curated.
- Where a Java handler exists, the comment follows the real runtime behavior.
- Where only legacy command texts exist, the comment marks the key as legacy and explains the intended behavior from those texts.
- Where a key is still present for compatibility but no direct handler is found in the current tree, the comment says so explicitly.
The new schema intentionally preserves legacy and inconsistent permission keys so current functionality stays intact.
Examples:
- `cmd_word_quiz`
- `cmd_wordquiz`
- `cms_dance`
- `kiss_cmd`
Those can be cleaned up later only after runtime behavior has been verified and the hotel no longer depends on the old names.
+382
View File
@@ -0,0 +1,382 @@
# Wired Bug Audit
## 1. Scopo
Questo documento raccoglie i **potenziali bug**, le **aree fragili** e le **incoerenze architetturali** emerse durante lanalisi del sistema wired.
Non tutti i punti qui sotto sono bug già riprodotti al 100%, ma sono:
- problemi già visti in comportamento reale
- incongruenze tra runtime e UI
- zone del codice che possono generare regressioni o risultati non deterministici
Riferimenti principali:
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java`
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredEngine.java`
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java`
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredMoveCarryHelper.java`
- `Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired`
---
## 2. Sintesi Priorità
| Priorità | Tema | Stato |
|---|---|---|
| Alta | `context` variabili esposto ma non implementato davvero | Incoerenza forte |
| Alta | Doppio runtime (`WiredManager` vs `WiredHandler`) | Rischio architetturale |
| Alta | Ordine effect non sempre garantito senza extra esplicito | Rischio comportamentale |
| Alta | Path movimento legacy può ancora far trapelare update intermedi | Già osservato in stanza |
| Media | Tick a `50ms` ma delay wired in step da `500ms` | Semantica non uniforme |
| Media | Polling realtime `:wired` a `50ms` | Rischio carico/runtime noise |
| Media | `click furni` ora immediato, queue/cancel svuotati | Possibile regressione |
| Media | Semantica timestamp variabili non uniforme tra target types | Possibile confusione logica |
---
## 3. Audit Dettagliato
## 3.1 `context` nelle variabili: esposto ma non veramente supportato
- **Gravità:** Alta
- **Confidenza:** Alta
- **Area:** effetti/condizioni/extras variabili
### Problema
Nel layout e in parte della serializzazione compare il target `context`, ma in più punti il runtime lo rifiuta esplicitamente oppure restituisce direttamente `false`.
Questo crea una situazione pericolosa:
- il designer pensa che la feature esista
- il box si salva o si configura parzialmente
- ma poi in esecuzione non produce il comportamento atteso
### Evidenze
- `WiredEffectGiveVariable.java:197`
- il save rifiuta `TARGET_CONTEXT`
- `WiredConditionVariableValueMatch.java:181`
- `case TARGET_CONTEXT -> false`
- `WiredConditionVariableAgeMatch.java:146`
- `case TARGET_CONTEXT -> false`
- `WiredExtraTextOutputVariable.java:83`
- il save rifiuta `TARGET_CONTEXT`
### Impatto pratico
- stack che sembrano validi in UI ma non funzionano a runtime
- falsi negativi nelle condition variabili
- placeholder testuali variabili non disponibili quando lutente si aspetta il target context
### Fix suggerito
Scegliere una direzione netta:
1. **o** implementare davvero `context` in tutti i flow variabili
2. **o** rimuoverlo completamente da UI, save e runtime finché non è pronto
La seconda opzione è la più sicura nel breve periodo.
---
## 3.2 Doppio runtime wired ancora presente
- **Gravità:** Alta
- **Confidenza:** Alta
- **Area:** architettura core
### Problema
`WiredManager` dichiara di essere il runtime esclusivo e tratta i vecchi flag come sola compatibilità, ma `WiredHandler` esiste ancora con entrypoint completi e logica propria.
### Evidenze
- `WiredManager.java:136`
- warning esplicito: `wired.engine.enabled / wired.engine.exclusive are now compatibility-only flags`
- `WiredManager.java:174`
- `isEnabled()` dipende solo dallinizializzazione del manager
- `WiredManager.java:182`
- `isExclusive()` ritorna sempre `true`
- `WiredHandler.java:63`
- entrypoint legacy completo `handle(...)`
- `WiredHandler.java:114`
- supporto separato per `handleCustomTrigger(...)`
### Impatto pratico
Se qualunque pezzo di codice, plugin o path legacy entra ancora in `WiredHandler`, si possono avere:
- ordine effect diverso
- scheduling delay diverso
- condition flow diverso
- diagnostica/monitor non coerente col nuovo engine
### Fix suggerito
- definire un solo entrypoint runtime ufficiale
- se `WiredHandler` deve restare, trasformarlo in adapter minimo che inoltra sempre al nuovo engine
- aggiungere log o metriche per rilevare qualsiasi ingresso nel path legacy
---
## 3.3 Ordine degli effect non sempre deterministico senza `wf_xtra_exec_in_order`
- **Gravità:** Alta
- **Confidenza:** Alta
- **Area:** esecuzione stack
### Problema
Nel path legacy, lordinamento stabile viene applicato chiaramente solo in presenza di `wf_xtra_exec_in_order` oppure in casi specifici (`unseen`).
Negli altri casi, lordine si appoggia alla collezione che arriva dal runtime.
### Evidenze
- `WiredHandler.java:224`
- rileva `hasExtraExecuteInOrder`
- `WiredHandler.java:230`
- ordina con `WiredExecutionOrderUtil.sort(effects)` solo in alcuni casi
- `WiredHandler.java:249`
- usa direttamente `effectList` in ordered mode
### Impatto pratico
Stack come:
- `move_rotate` + `match_to_sshot`
- `toggle` + `reset`
- `give_var` + `change_var_val`
possono produrre risultati diversi se si assume implicitamente un ordine che il runtime non promette davvero.
### Fix suggerito
- decidere se lordine stack deve essere sempre stabile di default
- in alternativa, mantenere la regola attuale ma documentarla in modo molto esplicito
- se si lascia la regola attuale, conviene segnalare in UI che lordine è garantito solo con `wf_xtra_exec_in_order`
---
## 3.4 Il path movimento legacy può ancora far vedere movimenti intermedi
- **Gravità:** Alta
- **Confidenza:** Alta
- **Area:** movement pipeline
### Problema
Il helper legacy di movimento usa ancora un fallback che, se il collector non è attivo, invia subito `FloorItemOnRollerComposer`.
Questo può far trapelare al client uno stato intermedio che in teoria avrebbe dovuto essere nascosto da batching o restore finale.
### Evidenze
- `WiredMoveCarryHelper.java:163`
- metodo `moveFurniLegacy(...)`
- `WiredMoveCarryHelper.java:179`
- usa il collector se disponibile
- `WiredMoveCarryHelper.java:196`
- fallback diretto a `FloorItemOnRollerComposer`
### Impatto pratico
È coerente con il tipo di bug già visto:
- oggetto che “si vede muovere”
- poi viene riportato nello stato corretto
- ma il client ha già ricevuto un update intermedio
### Fix suggerito
- evitare qualsiasi composer diretto nel path legacy quando la logica wired moderna è attiva
- centralizzare tutti i movement update in un unico collector finale
- aggiungere test specifici per:
- `move_rotate` + `match_to_sshot`
- stacked move effects nello stesso tick
---
## 3.5 Tick a `50ms`, ma delay wired ancora a step da `500ms`
- **Gravità:** Media
- **Confidenza:** Alta
- **Area:** semantica temporale
### Problema
Il sistema oggi ha due granularità temporali diverse:
- repeaters / tickables a `50ms`
- delay wired classico a `delay * 500ms`
### Evidenze
- `WiredTickService.java:48`
- `DEFAULT_TICK_INTERVAL_MS = 50`
- `WiredTickService.java:175`
- `scheduleAtFixedRate(...)`
- `WiredEngine.java:753`
- `long delayMs = delay * 500L`
- `WiredHandler.java:369`
- stesso schema `delay * 500L`
### Impatto pratico
Non è per forza un bug, ma può creare:
- aspettative sbagliate nel builder dei wired
- sensazione di desync tra repeater e delay
- stack “velocissimi” su tick ma “grossolani” sugli effect ritardati
### Fix suggerito
- o si accetta questa doppia semantica e la si documenta ovunque
- o si introduce una nuova famiglia di delay high-resolution separata dal delay classico
---
## 3.6 `:wired` realtime a `50ms` può diventare rumoroso/pesante
- **Gravità:** Media
- **Confidenza:** Alta
- **Area:** tooling monitor/inspection
### Problema
Le request di monitor e variabili ora sono rate-limitate a `50ms`.
### Evidenze
- `WiredMonitorRequestEvent.java:39`
- `return 50`
- `WiredUserVariablesRequestEvent.java:20`
- `return 50`
### Impatto pratico
Su una stanza attiva o con più client staff aperti:
- carico rete maggiore
- più rumore sul server
- rischio di mascherare problemi reali con spam di refresh
### Fix suggerito
- spostare dove possibile a push/event driven
- lasciare `50ms` solo per il minimo indispensabile
- differenziare:
- monitor heavy/debug
- inspection live
- variables snapshot
---
## 3.7 `click furni` ora è immediato: queue/cancel svuotati
- **Gravità:** Media
- **Confidenza:** Alta
- **Area:** eventi click furni
### Problema
La queue dei click furni è stata semplificata: ora il click parte subito, e il cancel path è vuoto.
### Evidenze
- `WiredManager.java:274`
- `queueUserClicksFurni(...)` chiama subito `triggerUserClicksFurni(...)`
- `WiredManager.java:282`
- `cancelPendingUserClicksFurni(...)` non fa nulla
### Impatto pratico
Se qualche comportamento vecchio dipendeva da:
- debounce
- cancel
- click differito
ora può cambiare senza che il mapping sia ovvio.
### Fix suggerito
- decidere se il comportamento immediato è quello definitivo
- se sì, documentarlo come breaking behavior
- se no, reintrodurre una queue reale con semantica esplicita
---
## 3.8 Semantica timestamp variabili non uniforme tra target type
- **Gravità:** Media
- **Confidenza:** Media
- **Area:** sistema variabili
### Problema
Le variabili utente e furni hanno senso come “assegnazione con creation/update time”, mentre le room/global variables hanno soprattutto senso sul solo `update time`.
Questo può diventare ambiguo quando si usano:
- `wf_cnd_var_age_match`
- sorting per creation/update
- UI manage/inspection
### Evidenze
- `WiredConditionVariableAgeMatch.java`
- il target room/global vive soprattutto come valore di update
- le scelte di prodotto già fatte in `:wired` vanno in questa direzione
### Impatto pratico
- il builder può pensare che “tempo di creazione” sulle global sia forte quanto sulle user/furni
- condition o sort possono essere semanticamente strani anche se “funzionano”
### Fix suggerito
- trattare esplicitamente `room/global` come `updated-only`
- disabilitare in UI le opzioni che non hanno senso forte
- o documentare in modo molto chiaro la differenza
---
## 4. Backlog Consigliato
Ordine suggerito di intervento:
1. **Chiudere il target `context`**
- o implementarlo davvero
- o toglierlo da UI/save/runtime
2. **Unificare il runtime**
- lasciare un solo entrypoint ufficiale
3. **Stabilire la regola sullordine effect**
- default stabile o ordine esplicito con extra
4. **Chiudere il leak dei movement update legacy**
- niente composer fuori collector quando wired moderno è attivo
5. **Ripensare il realtime di `:wired`**
- spostare il più possibile da polling a push
---
## 5. Nota Finale
Il sistema wired attuale è già molto più potente del modello classico, soprattutto per:
- variabili
- signal routing
- selectors avanzati
- monitor
- manage/inspection
Proprio per questo, le zone fragili oggi non sono tanto i box semplici, ma:
- la coesistenza di due runtime
- la semantica temporale
- i movement stack
- le feature variabili ancora “mezze esposte”
Questi sono i punti che più probabilmente spiegano i bug strani o intermittenti.
+500
View File
@@ -0,0 +1,500 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Riferimento Completo Wired</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
wired: {
50: '#eef7ff',
100: '#d9ecff',
200: '#b8dbff',
300: '#89c0ff',
400: '#569dff',
500: '#2d77ff',
600: '#1f5ee5',
700: '#1d4dcb',
800: '#1e42a4',
900: '#1d397f'
}
},
boxShadow: {
wired: '0 20px 50px rgba(15, 23, 42, 0.14)'
}
}
}
};
</script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
html {
scroll-behavior: smooth;
}
body {
background:
radial-gradient(circle at top left, rgba(45, 119, 255, 0.12), transparent 35%),
radial-gradient(circle at top right, rgba(14, 165, 233, 0.10), transparent 30%),
linear-gradient(180deg, #f8fbff 0%, #f1f5f9 100%);
}
.doc-content h1,
.doc-content h2,
.doc-content h3,
.doc-content h4 {
scroll-margin-top: 110px;
}
.doc-content h1 {
font-size: 2.5rem;
line-height: 1.1;
font-weight: 800;
color: #0f172a;
margin-bottom: 1.25rem;
}
.doc-content h2 {
font-size: 1.65rem;
line-height: 1.2;
font-weight: 800;
color: #0f172a;
margin-top: 3rem;
margin-bottom: 1rem;
padding-bottom: 0.6rem;
border-bottom: 1px solid #dbeafe;
}
.doc-content h3 {
font-size: 1.15rem;
line-height: 1.45;
font-weight: 700;
color: #1e3a8a;
margin-top: 1.75rem;
margin-bottom: 0.85rem;
background: #eff6ff;
border: 1px solid #dbeafe;
border-radius: 0.9rem;
padding: 0.75rem 1rem;
}
.doc-content h4 {
font-size: 1rem;
font-weight: 700;
color: #1e293b;
margin-top: 1.25rem;
margin-bottom: 0.5rem;
}
.doc-content p,
.doc-content li {
color: #334155;
line-height: 1.78;
}
.doc-content p {
margin: 0.75rem 0;
}
.doc-content ul,
.doc-content ol {
margin: 0.85rem 0 1rem 1.4rem;
}
.doc-content ul {
list-style: disc;
}
.doc-content ol {
list-style: decimal;
}
.doc-content li {
margin: 0.35rem 0;
padding-left: 0.2rem;
}
.doc-content hr {
border: 0;
height: 1px;
background: linear-gradient(90deg, transparent, #bfdbfe, transparent);
margin: 2.25rem 0;
}
.doc-content code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
background: #eff6ff;
color: #1d4ed8;
padding: 0.16rem 0.38rem;
border-radius: 0.45rem;
font-size: 0.92em;
}
.doc-content pre {
background: #0f172a;
color: #e2e8f0;
padding: 1rem 1.1rem;
border-radius: 1rem;
overflow-x: auto;
margin: 1rem 0 1.25rem;
box-shadow: inset 0 0 0 1px rgba(148, 163, 184, 0.15);
}
.doc-content pre code {
background: transparent;
color: inherit;
padding: 0;
}
.doc-content table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0 1.5rem;
overflow: hidden;
border-radius: 1rem;
box-shadow: inset 0 0 0 1px #dbeafe;
}
.doc-content thead tr {
background: #dbeafe;
}
.doc-content th,
.doc-content td {
text-align: left;
padding: 0.8rem 0.95rem;
border-bottom: 1px solid #e2e8f0;
color: #334155;
vertical-align: top;
}
.doc-content th {
font-weight: 700;
color: #0f172a;
}
.doc-content tbody tr:nth-child(even) {
background: #f8fbff;
}
.doc-content blockquote {
margin: 1rem 0;
padding: 0.9rem 1rem;
border-left: 4px solid #60a5fa;
background: #f8fbff;
border-radius: 0 0.9rem 0.9rem 0;
}
.toc-link.active {
background: #dbeafe;
color: #1d4ed8;
font-weight: 600;
}
</style>
</head>
<body class="min-h-screen text-slate-800">
<div class="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8">
<header class="mb-6 rounded-3xl border border-white/70 bg-white/85 p-6 shadow-wired backdrop-blur">
<div class="flex flex-col gap-6 lg:flex-row lg:items-start lg:justify-between">
<div class="max-w-3xl">
<div class="mb-3 inline-flex items-center gap-2 rounded-full border border-wired-200 bg-wired-50 px-3 py-1 text-xs font-semibold uppercase tracking-[0.18em] text-wired-700">
<span class="h-2 w-2 rounded-full bg-wired-500"></span>
Documentazione tecnica Wired
</div>
<h1 class="text-3xl font-extrabold tracking-tight text-slate-900 sm:text-4xl">
Riferimento Completo Wired
</h1>
<p class="mt-3 text-sm leading-7 text-slate-600 sm:text-base">
Questa pagina renderizza <code>wired_full_reference.md</code> in una vista HTML consultabile,
con struttura e interfaccia in italiano. Gli identificatori tecnici dei wired, delle classi e
delle chiavi restano invariati per mantenere la documentazione fedele al runtime.
</p>
</div>
<div class="grid gap-3 sm:grid-cols-3 lg:w-[28rem]">
<div class="rounded-2xl border border-slate-200 bg-slate-50 p-4">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Sorgente</div>
<div class="mt-1 text-sm font-medium text-slate-800">Markdown vivo</div>
<div class="mt-1 text-xs text-slate-500">La pagina legge il file `.md` locale.</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 p-4">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Lingua</div>
<div class="mt-1 text-sm font-medium text-slate-800">Interfaccia italiana</div>
<div class="mt-1 text-xs text-slate-500">Struttura e metadati localizzati.</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 p-4">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Stile</div>
<div class="mt-1 text-sm font-medium text-slate-800">Tailwind CDN</div>
<div class="mt-1 text-xs text-slate-500">Layout leggibile, sticky nav e indice.</div>
</div>
</div>
</div>
</header>
<div class="grid gap-6 lg:grid-cols-[19rem,minmax(0,1fr)]">
<aside class="lg:sticky lg:top-6 lg:self-start">
<div class="rounded-3xl border border-white/70 bg-white/90 p-4 shadow-wired backdrop-blur">
<div class="mb-4">
<label for="toc-search" class="mb-2 block text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">
Cerca sezione
</label>
<input
id="toc-search"
type="text"
placeholder="Es. variabili, trigger, signal..."
class="w-full rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-700 outline-none transition focus:border-wired-300 focus:bg-white focus:ring-2 focus:ring-wired-100"
/>
</div>
<div class="mb-4 rounded-2xl border border-amber-200 bg-amber-50/80 p-3 text-xs leading-6 text-amber-900">
<div class="font-semibold">Nota</div>
<div>
La pagina mantiene nomi wired, classi Java e chiavi tecniche così come sono nel progetto.
</div>
</div>
<div class="mb-3 flex items-center justify-between">
<h2 class="text-sm font-semibold text-slate-900">Indice</h2>
<a
href="./wired_full_reference.md"
class="rounded-full border border-slate-200 px-3 py-1 text-xs font-medium text-slate-600 transition hover:border-wired-300 hover:text-wired-700"
>
Apri Markdown
</a>
</div>
<nav id="toc" class="space-y-1 text-sm"></nav>
</div>
</aside>
<main>
<section class="mb-6 rounded-3xl border border-white/70 bg-white/90 p-5 shadow-wired backdrop-blur">
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h2 class="text-lg font-bold text-slate-900">Panoramica</h2>
<p class="mt-1 text-sm leading-7 text-slate-600">
Trovi allinizio le regole del motore wired, poi il catalogo completo di trigger, effect,
selector, condition, extra e variabili.
</p>
</div>
<div class="flex flex-wrap gap-2 text-xs font-medium">
<span class="rounded-full bg-wired-50 px-3 py-2 text-wired-700">Engine + Tick</span>
<span class="rounded-full bg-emerald-50 px-3 py-2 text-emerald-700">154 wired catalogati</span>
<span class="rounded-full bg-fuchsia-50 px-3 py-2 text-fuchsia-700">HTML da Markdown</span>
</div>
</div>
</section>
<article class="rounded-3xl border border-white/70 bg-white/95 p-6 shadow-wired backdrop-blur sm:p-8">
<div id="loading" class="rounded-2xl border border-slate-200 bg-slate-50 p-5 text-sm text-slate-600">
Caricamento della reference in corso...
</div>
<div id="error" class="hidden rounded-2xl border border-rose-200 bg-rose-50 p-5 text-sm text-rose-700"></div>
<div id="content" class="doc-content hidden"></div>
</article>
</main>
</div>
</div>
<script>
const headingTranslations = new Map([
['# Wired Full Reference', '# Riferimento Completo Wired'],
['## 1. Scope', '## 1. Ambito'],
['## 2. Wired Engine, Tick, and General Runtime Rules', '## 2. Motore Wired, Tick e Regole Generali del Runtime'],
['## 3. Triggers', '## 3. Trigger'],
['## 4. Effects', '## 4. Effetti'],
['## 5. Selectors', '## 5. Selettori'],
['## 6. Conditions', '## 6. Condizioni'],
['## 7. Extras', '## 7. Extra'],
['## 8. Variable Definitions', '## 8. Definizioni Variabili'],
['## 9. Special Wired Items', '## 9. Elementi Wired Speciali'],
['## 10. Practical Design Notes', '## 10. Note Pratiche di Progettazione'],
['## 11. Quick Alias / Shared Runtime Notes', '## 11. Alias Rapidi e Note sul Runtime Condiviso'],
['### General selector notes', '### Note generali sui selettori'],
['### General condition notes', '### Note generali sulle condizioni']
]);
const lineTranslations = [
[/^- \*\*Class:\*\*/g, '- **Classe:**'],
[/^- \*\*Behavior:\*\*/g, '- **Comportamento:**'],
[/^- \*\*Main settings:\*\*/g, '- **Impostazioni principali:**'],
[/^- \*\*Notes:\*\*/g, '- **Note:**'],
[/^- \*\*Supported operations:\*\*/g, '- **Operazioni supportate:**'],
[/^- \*\*Supported sort modes:\*\*/g, '- **Modalità di ordinamento supportate:**']
];
const paragraphTranslations = new Map([
['This document is a code-based reference for the current wired runtime in `Arcturus-Morningstar-Extended`.', 'Questo documento è un riferimento tecnico basato sul codice per il runtime wired attuale di `Arcturus-Morningstar-Extended`.'],
['It covers:', 'Copre:'],
['Primary runtime sources used for this reference:', 'Sorgenti principali del runtime usate per questa reference:'],
['This file is meant to describe the runtime behavior and configuration surface, not the Nitro UI layout in detail. For `:wired` monitor and inspection tooling, also see `Arcturus-Morningstar-Extended/docs/wired_tools_reference.md`.', 'Questo file descrive il comportamento del runtime e la superficie di configurazione, non il layout Nitro nel dettaglio. Per gli strumenti `:wired` di monitor e inspection, vedi anche `Arcturus-Morningstar-Extended/docs/wired_tools_reference.md`.'],
['The modern wired runtime is centered around these components:', 'Il runtime wired moderno ruota attorno a questi componenti:'],
['At a high level, the engine processes a stack like this:', 'A livello alto, il motore processa uno stack in questo modo:'],
['Important consequences of this model:', 'Conseguenze importanti di questo modello:'],
['The centralized tick service is defined in `WiredTickService`.', 'Il servizio tick centralizzato è definito in `WiredTickService`.'],
['Current core rules:', 'Regole principali attuali:'],
['This means:', 'Questo significa:'],
['The classic wired delay value is stored in half-second steps.', 'Il valore classico del delay wired è memorizzato in step da mezzo secondo.'],
['Runtime rule:', 'Regola runtime:'],
['Examples:', 'Esempi:'],
['There are several separate notions of order:', 'Esistono più concetti distinti di ordine di esecuzione:'],
['Practical takeaway:', 'Conclusione pratica:'],
['Selectors build or refine the `WiredTargets` inside `WiredContext`.', 'I selettori costruiscono o raffinano i `WiredTargets` dentro `WiredContext`.'],
['In practice:', 'In pratica:'],
['Conditions are evaluated after selectors.', 'Le condizioni vengono valutate dopo i selettori.'],
['General behavior:', 'Comportamento generale:'],
['The runtime supports both:', 'Il runtime supporta sia:'],
['The wired runtime has multiple safety layers:', 'Il runtime wired ha più livelli di protezione:'],
['Main defaults from runtime/config:', 'Default principali da runtime/config:'],
['The new engine tracks room diagnostics through `WiredRoomDiagnostics`.', 'Il nuovo motore traccia le diagnostiche stanza tramite `WiredRoomDiagnostics`.'],
['This is where `:wired` monitor gets values such as:', 'È da qui che il monitor `:wired` ottiene valori come:'],
['Heavy/overload decisions are based on rolling windows, not on a single event.', 'Le decisioni di heavy/overload si basano su finestre scorrevoli, non su un singolo evento.'],
['The project still contains `WiredHandler`.', 'Il progetto contiene ancora `WiredHandler`.'],
['Important practical notes:', 'Note pratiche importanti:'],
['So when documenting stacks, it is best to think in terms of:', 'Quindi, quando si documentano gli stack, conviene ragionare in termini di:'],
['Custom wired variables are defined by:', 'Le variabili wired custom sono definite da:'],
['Shared rules:', 'Regole condivise:'],
['Availability rules:', 'Regole di disponibilità:'],
['Timestamp rules:', 'Regole sui timestamp:'],
['Current context-status note:', 'Nota sullo stato del contesto:'],
['These are part of the wired ecosystem, even if they are not regular trigger/effect/selector/condition/extra boxes.', 'Questi fanno parte dellecosistema wired anche se non sono box classici trigger/effect/selector/condition/extra.'],
['Use:', 'Usa:'],
['Remember:', 'Ricorda:'],
['Check:', 'Controlla:']
]);
function normalizeText(raw) {
return raw
.replace(/“/g, '“')
.replace(/”/g, '”')
.replace(/’/g, '')
.replace(/–/g, '')
.replace(/—/g, '—')
.replace(/…/g, '…');
}
function localizeMarkdown(raw) {
let output = normalizeText(raw);
headingTranslations.forEach((translated, original) => {
output = output.replace(original, translated);
});
paragraphTranslations.forEach((translated, original) => {
output = output.replaceAll(original, translated);
});
lineTranslations.forEach(([regex, replacement]) => {
output = output.replace(regex, replacement);
});
return output;
}
function slugify(text) {
return text
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/[`"'’“”]/g, '')
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
}
function buildToc() {
const toc = document.getElementById('toc');
const headings = [...document.querySelectorAll('#content h2, #content h3')];
toc.innerHTML = '';
headings.forEach((heading) => {
const text = heading.textContent.trim();
const id = slugify(text);
heading.id = id;
const link = document.createElement('a');
link.href = `#${id}`;
link.textContent = text;
link.className =
`toc-link block rounded-2xl px-3 py-2 transition hover:bg-slate-100 hover:text-wired-700 ${
heading.tagName === 'H3' ? 'ml-3 text-xs text-slate-500' : 'text-sm font-medium text-slate-700'
}`;
toc.appendChild(link);
});
}
function wireSearch() {
const search = document.getElementById('toc-search');
const toc = document.getElementById('toc');
search.addEventListener('input', () => {
const needle = search.value.trim().toLowerCase();
const links = [...toc.querySelectorAll('a')];
links.forEach((link) => {
const visible = !needle || link.textContent.toLowerCase().includes(needle);
link.classList.toggle('hidden', !visible);
});
});
}
function wireActiveSection() {
const links = [...document.querySelectorAll('#toc a')];
const headingMap = links
.map((link) => {
const target = document.querySelector(link.getAttribute('href'));
return target ? { link, target } : null;
})
.filter(Boolean);
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const item = headingMap.find(({ target }) => target === entry.target);
if (!item) return;
item.link.classList.toggle('active', entry.isIntersecting);
});
},
{ rootMargin: '-20% 0px -70% 0px', threshold: 0 }
);
headingMap.forEach(({ target }) => observer.observe(target));
}
async function loadReference() {
const loading = document.getElementById('loading');
const error = document.getElementById('error');
const content = document.getElementById('content');
try {
const response = await fetch('./wired_full_reference.md');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const raw = await response.text();
const localized = localizeMarkdown(raw);
const html = marked.parse(localized, { mangle: false, headerIds: false });
content.innerHTML = html;
content.classList.remove('hidden');
loading.classList.add('hidden');
buildToc();
wireSearch();
wireActiveSection();
} catch (err) {
loading.classList.add('hidden');
error.classList.remove('hidden');
error.textContent = `Impossibile caricare wired_full_reference.md (${err.message}).`;
}
}
loadReference();
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
+283
View File
@@ -0,0 +1,283 @@
# Wired Creator Tools Implementation Summary
## 1. Purpose
This document summarizes the `:wired` work completed in this development cycle.
It is intended as a project-facing summary of:
- what was added
- where it lives
- what is already working
- what is still intentionally left as future work
---
## 2. Main goals completed
The current `:wired` implementation now provides:
1. a dedicated Nitro UI window
2. monitor and inspection tooling
3. room/user/furni/global variable views
4. inline editing for selected values
5. live wired diagnostics from the server
6. error/warning history with details
7. server-side diagnostics configuration through DB settings
---
## 3. Nitro-V3 work
Main file:
- `Nitro-V3/src/components/wired-tools/WiredCreatorToolsView.tsx`
### 3.1 UI window
The `:wired` tool now has these main tabs:
- `Monitor`
- `Variables`
- `Inspection`
- `Chests`
- `Settings`
Current active work is mainly in:
- `Monitor`
- `Inspection`
`Chests` and `Settings` are currently placeholder/future-facing areas.
### 3.2 Inspection
Implemented:
- element type switcher (`furni`, `user`, `global`)
- preview area
- variable table
- `Keep selected`
- inline editing
#### Furni
Added support for:
- detailed furni variables
- live preview
- wall/floor-specific handling
- teleport metadata
- inline edits for state/position/rotation/altitude/wall offset
#### User
Added support for:
- user/bot/pet identity
- rights / owner / group admin flags
- mute / trading / frozen flags
- team / sign / dance / idle / hand item / effect display
- room entry method and teleport entry id
- inline edits for position and direction
#### Global
Added support for:
- room counts
- wired timer
- team scores and sizes
- room/group ids
- server/client timezone
- current server time breakdown
### 3.3 Monitor
Implemented:
- live stats table
- log summary list
- full log history
- info/documentation popup
- error information popup
The auxiliary monitor windows now use proper Nitro card windows, so they are:
- draggable
- resizable
- closed through the normal Nitro close button
---
## 4. Nitro_Render_V3 work
Renderer-side work was focused on making Nitro receive enough metadata for the new UI.
Main areas:
- new wired monitor packet parsing
- room/session metadata extensions
- furni metadata extensions
- user metadata extensions
### 4.1 Monitor data
The renderer now parses and exposes:
- usage budget values
- delayed queue values
- execution timing values
- heavy/overload thresholds
- current logs
- history rows
### 4.2 Room metadata
The renderer/session flow was extended to expose values used by Nitro:
- room furni limit
- room group id
- hotel timezone / hotel time snapshot
### 4.3 Furni metadata
The furni info path now exposes values used by the inspector, including:
- dimensions
- `items_base`-driven flags such as sit/lay/stand/stack
- teleport target metadata
### 4.4 User metadata
The user/unit data path now exposes values used by the inspector, including:
- room entry method
- room entry teleport id
- identity data for user/bot/pet
---
## 5. Emulator work
Main areas:
- wired diagnostics engine
- monitor request/response packet
- room/user/furni metadata support
- configuration migration to `wired_emulator_settings`
### 5.1 Wired diagnostics
Added server-side room diagnostics with:
- usage budget tracking
- delayed event queue tracking
- average/peak execution timing
- overload detection
- heavy-room detection
- recursion protection logging
- killed-room protection logging
### 5.2 Diagnostics logs
Logs now carry:
- type
- severity
- count
- reason
- source label
- source id
- history entries with occurrence timestamps
### 5.3 Trigger/runtime fixes
Important behaviour fixes added during this work:
- empty repeater stacks no longer count as executable work
- monitor usage is consumed later in the execution path, closer to real execution
- timer/repeater behaviour is less noisy in diagnostics
### 5.4 Monitor packet
A dedicated request/response path was added so Nitro can poll live room diagnostics.
### 5.5 Configuration migration
All wired config is being moved out of `emulator_settings` and into:
- `wired_emulator_settings`
This now includes both:
- existing wired runtime settings
- the new `:wired` monitor threshold settings
Migration file:
- `Database Updates/002_move_wired_settings_to_wired_emulator_settings.sql`
---
## 6. What the monitor currently measures
The monitor currently measures:
- execution budget consumed in the current server window
- delayed events currently pending
- average execution time inside the current window
- peak execution time inside the current window
- recursion depth
- remaining killed-room cooldown
- room heavy state
- room furni counts
- renderer custom variable counts on room items
---
## 7. What is configurable now
Current DB-configurable areas include:
- engine enable/debug/exclusive/max-steps
- custom wired compatibility mode
- furni selection limit
- max delay / max text length
- teleport delay
- tick interval/debug/priority
- abuse protection thresholds
- monitor usage/delayed/heavy/overload thresholds
All of these are documented in:
- `docs/wired_tools_reference.md`
---
## 8. Known limitations / future work
Current known limitations:
- `Permanent furni vars` uses a fixed UI denominator (`60`)
- `@wired_timer` is still client-side time since room entry
- `Chests` and `Settings` are not fully implemented yet
- legacy wired configuration keys are still present for database compatibility, but runtime execution now goes only through the new engine
Good future tasks:
- make `Permanent furni vars` fully server-driven
- add export/copy actions for monitor history
- add more detailed filtering/search in history
- document chest/settings once implemented
- optionally remove the compatibility keys entirely once old database defaults are no longer needed
---
## 9. Recommended rollout order
1. run the wired settings migration SQL
2. restart the emulator
3. refresh renderer/client
4. verify monitor values in a real room
5. tune `wired.monitor.*` thresholds using the new DB table
+554
View File
@@ -0,0 +1,554 @@
# Wired Creator Tools (`:wired`) Reference
## 1. Scope
This document describes the current `:wired` tooling that was added across:
- `Arcturus-Morningstar-Extended` (server-side data, diagnostics, config)
- `Nitro_Render_V3` (packet parsing and room/session metadata)
- `Nitro-V3` (UI, monitor, inspection, previews, inline editing)
It focuses on:
- the `Monitor` tab
- the `Inspection` tab (`furni`, `user`, `global`)
- the `wired_emulator_settings` database table
- the formulas and thresholds behind the monitor statistics
---
## 2. High-level architecture
### 2.1 Data flow
`Emulator` -> `Nitro_Render_V3` -> `Nitro-V3`
- The emulator computes room diagnostics and exposes extra room, furni, user, and monitor metadata.
- The renderer parses those packets and stores the values in room/session data objects.
- Nitro reads those values and renders them in the `:wired` UI.
### 2.2 Main files
- Emulator diagnostics:
- `Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredEngine.java`
- `Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredRoomDiagnostics.java`
- `Emulator/src/main/java/com/eu/habbo/messages/outgoing/wired/WiredMonitorDataComposer.java`
- Renderer parsing:
- `Nitro_Render_V3/packages/communication/src/messages/parser/roomevents/WiredMonitorDataParser.ts`
- Nitro UI:
- `Nitro-V3/src/components/wired-tools/WiredCreatorToolsView.tsx`
---
## 3. Database configuration
## 3.1 New table
Wired configuration is now separated from `emulator_settings` into:
```sql
wired_emulator_settings (
key,
value,
comment
)
```
Migration file:
- `Database Updates/002_move_wired_settings_to_wired_emulator_settings.sql`
The migration:
1. creates `wired_emulator_settings`
2. imports existing wired values from `emulator_settings`
3. inserts defaults for new monitor/diagnostic keys when missing
4. removes migrated wired keys from `emulator_settings`
### 3.2 Compatibility behaviour
The emulator still has a **fallback read path**:
- first it reads wired keys from `wired_emulator_settings`
- if a wired key is still missing there, it can still read it from the old `emulator_settings`
This allows safe rollout during migration.
## 3.3 Wired configuration keys
| Key | Default | Purpose |
|---|---:|---|
| `wired.engine.enabled` | `1` | Compatibility flag kept for old configs. Wired now runs through the new engine only. |
| `wired.engine.exclusive` | `1` | Compatibility flag kept for old configs. Wired now runs through the new engine only. |
| `wired.engine.maxStepsPerStack` | `100` | Maximum internal processing steps allowed for one stack execution. |
| `wired.engine.debug` | `0` | Enables verbose wired engine logging. |
| `wired.custom.enabled` | `0` | Enables legacy custom wired compatibility logic. |
| `hotel.wired.furni.selection.count` | `5` | Maximum furni count selectable/storable by wired boxes. |
| `hotel.wired.max_delay` | `20` | Maximum accepted wired delay value for delayed effects. |
| `hotel.wired.message.max_length` | `100` | Maximum length of wired/bot text fields. |
| `wired.effect.teleport.delay` | `500` | Delay in milliseconds used by wired teleports. |
| `wired.place.under` | `0` | Allows wired furniture placement under other items. |
| `wired.tick.interval.ms` | `50` | Global tick interval in milliseconds for repeater-style wired. |
| `wired.tick.resolution` | `100` | Legacy compatibility tick resolution value. |
| `wired.tick.debug` | `0` | Enables verbose logging for the tick service. |
| `wired.tick.thread.priority` | `6` | Java thread priority for the tick service. |
| `wired.highscores.displaycount` | `25` | Maximum wired highscore entries shown to the user. |
| `wired.abuse.max.recursion.depth` | `10` | Maximum recursive wired depth before execution stops. |
| `wired.abuse.max.events.per.window` | `100` | Maximum identical events allowed inside the abuse rate-limit window. |
| `wired.abuse.rate.limit.window.ms` | `10000` | Time window in milliseconds used by the abuse limiter. |
| `wired.abuse.ban.duration.ms` | `600000` | Room wired-ban duration in milliseconds after abuse detection. |
| `wired.monitor.usage.window.ms` | `1000` | Rolling window size used to calculate monitor usage. |
| `wired.monitor.usage.limit` | `1000` | Maximum usage budget allowed in one monitor window. |
| `wired.monitor.delayed.events.limit` | `100` | Maximum delayed wired events that may be pending in one room. |
| `wired.monitor.overload.average.ms` | `50` | Average execution threshold in milliseconds for overload tracking. |
| `wired.monitor.overload.peak.ms` | `150` | Peak execution threshold in milliseconds for overload tracking. |
| `wired.monitor.overload.consecutive.windows` | `2` | Consecutive overloaded windows required before `EXECUTOR_OVERLOAD`. |
| `wired.monitor.heavy.usage.percent` | `70` | Usage percentage threshold that contributes to `MARKED_AS_HEAVY`. |
| `wired.monitor.heavy.consecutive.windows` | `5` | Consecutive heavy windows required before the room is marked heavy. |
| `wired.monitor.heavy.delayed.percent` | `60` | Delayed queue percentage threshold that contributes to the heavy state. |
---
## 4. Monitor tab
## 4.1 Statistics shown in the UI
The `Monitor` tab currently shows:
- `Wired usage`
- `Is heavy`
- `Room furni`
- `Wall furni`
- `Delayed events`
- `Average execution`
- `Peak execution`
- `Recursion`
- `Killed remaining`
- `Permanent furni vars`
### 4.1.1 `Wired usage`
Format:
```text
usageCurrentWindow / usageLimitPerWindow
```
Source:
- server-side `WiredRoomDiagnostics`
Meaning:
- `usageCurrentWindow` = cost consumed in the current rolling monitor window
- `usageLimitPerWindow` = max allowed budget before `EXECUTION_CAP`
### 4.1.2 `Is heavy`
Format:
```text
Yes / No
```
Source:
- server-side boolean from `WiredRoomDiagnostics`
Meaning:
- `Yes` if the room has crossed the heavy thresholds for enough consecutive windows
### 4.1.3 `Room furni`
Format:
```text
(floor count + wall count) / roomItemLimit
```
Source:
- numerator: renderer room object counts
- denominator: server room item limit exposed in room/session data
### 4.1.4 `Wall furni`
Format:
```text
wall count / roomItemLimit
```
Important note:
- there is **no separate wall-only cap** here
- the denominator is the same room furni limit exposed by the server
### 4.1.5 `Delayed events`
Format:
```text
delayedEventsPending / delayedEventsLimit
```
Source:
- server-side `WiredRoomDiagnostics`
### 4.1.6 `Average execution`
Format:
```text
averageExecutionMs + "ms"
```
Meaning:
- average execution time of sampled stacks inside the current monitor window
### 4.1.7 `Peak execution`
Format:
```text
peakExecutionMs + "ms"
```
Meaning:
- highest sampled execution time inside the current monitor window
### 4.1.8 `Recursion`
Format:
```text
recursionDepthCurrent / recursionDepthLimit
```
Meaning:
- current nested wired call depth vs the configured recursion cap
### 4.1.9 `Killed remaining`
Format:
```text
killedRemainingSeconds + "s"
```
Meaning:
- remaining room cooldown while wired execution is temporarily halted by protection logic
### 4.1.10 `Permanent furni vars`
Format:
```text
customVariableEntryCount / 60
```
Current meaning:
- the numerator is the total number of renderer-side entries stored inside `RoomObjectVariable.FURNITURE_CUSTOM_VARIABLES`
- the denominator `60` is currently a fixed UI denominator
This is currently **renderer-side custom variable count**, not a DB row count.
---
## 4.2 Cost model behind `Wired usage`
The current estimated stack cost is computed in the emulator.
### 4.2.1 Base formula
```text
cost = 1
cost += number_of_conditions
cost += 2 for each selector effect
cost += 3 for each non-selector effect
cost += 4 extra for each delayed effect
cost += recursionDepth * 2
cost = max(1, cost)
```
### 4.2.2 Practical breakdown
| Element | Cost |
|---|---:|
| Base stack cost | `1` |
| Each condition | `+1` |
| Each selector effect | `+2` |
| Each regular effect | `+3` |
| Each delayed effect | `+4` extra |
| Each recursion level | `+2` |
### 4.2.3 Example
If a stack has:
- `2` conditions
- `1` selector
- `2` normal effects
- `1` delayed effect
- recursion depth `1`
Then:
```text
1
+ 2 conditions
+ 2 selector
+ 6 regular effects
+ 4 delayed effect extra
+ 2 recursion
= 17
```
That `17` is what is attempted against:
```text
usageCurrentWindow + estimatedCost <= usageLimitPerWindow
```
If the result would exceed the budget, the engine records `EXECUTION_CAP`.
---
## 4.3 Heavy / overload calculations
### 4.3.1 Overload
A monitor window is considered overloaded when:
```text
executionSamplesCurrentWindow > 0
AND (
averageExecutionMs >= overloadAverageThresholdMs
OR
peakExecutionMs >= overloadPeakThresholdMs
)
```
After `wired.monitor.overload.consecutive.windows` consecutive overloaded windows:
- the room logs `EXECUTOR_OVERLOAD`
### 4.3.2 Heavy
A monitor window is considered heavy when at least one of these is true:
```text
usagePercent >= heavyUsageThresholdPercent
OR
delayedPercent >= heavyDelayedThresholdPercent
OR
overloadWindow == true
```
Where:
```text
usagePercent = round(usageCurrentWindow * 100 / usageLimitPerWindow)
delayedPercent = round(delayedEventsPending * 100 / delayedEventsLimit)
```
After `wired.monitor.heavy.consecutive.windows` consecutive heavy windows:
- the room is marked heavy
- the monitor logs `MARKED_AS_HEAVY`
---
## 4.4 Error / warning log types
The monitor currently supports:
- `EXECUTION_CAP`
- `DELAYED_EVENTS_CAP`
- `EXECUTOR_OVERLOAD`
- `MARKED_AS_HEAVY`
- `KILLED`
- `RECURSION_TIMEOUT`
Each log/history entry can carry:
- type
- severity
- amount/count
- latest occurrence
- reason/motivation
- trigger/source label
- trigger/source id
---
## 5. Inspection tab
## 5.1 Furni inspection
Current variables include:
- `@id`
- `@class_id`
- `@height`
- `@state`
- `@position.x`
- `@position.y`
- `@rotation`
- `@altitude`
- `@wallitem_offset` (wall items only)
- `@type`
- `@dimensions.x`
- `@dimensions.y`
- `@owner_id`
- dynamic flags:
- `@can_sit_on`
- `@can_lay_on`
- `@can_stand_on`
- `@is_stackable`
- extra teleport variable when relevant:
- `~teleport.target_id`
Editable fields:
- `@state`
- `@position.x`
- `@position.y`
- `@rotation`
- `@altitude`
- `@wallitem_offset` (wall items)
Important notes:
- floor moves are sent through wired-style movement flow/animation
- wall item updates use wall position recomposition
- booleans such as sit/lay/stand/stack come from `items_base`-derived metadata, not from `FurnitureData.json`
## 5.2 User inspection
Current variables include:
- `@index`
- `@type`
- `@gender`
- `@level`
- `@achievement_score`
- `@position.x`
- `@position.y`
- `@direction`
- `@altitude`
- `@favourite_group_id`
- `@room_entry`
- `@room_entry.teleport_id`
- `@user_id` / `@bot_id` / `@pet_id`
Dynamic flags/actions include:
- `@is_hc`
- `@has_rights`
- `@is_owner`
- `@is_group_admin`
- `@is_mute`
- `@is_trading`
- `@is_frozen`
- `@effect`
- `@team_score`
- `@team_color`
- `@team_type`
- `@sign`
- `@dance`
- `@is_idle`
- `@handitems`
Editable fields:
- `@position.x`
- `@position.y`
- `@direction`
## 5.3 Global inspection
Current variables include:
- `@furni_count`
- `@user_count`
- `@wired_timer`
- `@teams.red.score`
- `@teams.green.score`
- `@teams.blue.score`
- `@teams.yellow.score`
- `@teams.red.size`
- `@teams.green.size`
- `@teams.blue.size`
- `@teams.yellow.size`
- `@room_id`
- `@group_id`
- `@timezone_server`
- `@timezone_client`
- `@current_time`
- `@current_time.millisecond_of_second`
- `@current_time.seconds_of_minute`
- `@current_time.minute_of_hour`
- `@current_time.hour_of_day`
- `@current_time.day_of_week`
- `@current_time.day_of_month`
- `@current_time.day_of_year`
- `@current_time.week_of_year`
- `@current_time.month_of_year`
- `@current_time.year`
Important notes:
- `@timezone_server` comes from the emulator room/session snapshot and follows `hotel.timezone`
- `@timezone_client` comes from the browser
- `@wired_timer` is currently client-side time since room entry
- `@current_time.*` is currently based on the server hotel time snapshot plus client-side progression
---
## 6. UI behaviour notes
### 6.1 Monitor windows
The monitor now uses real Nitro card windows for:
- info
- log history
- error information
This means they are:
- closable with the standard Nitro card close button
- draggable
- resizable
### 6.2 Keep selected
In `Inspection`:
- when `Keep selected` is enabled
- clicking another furni/user does **not** replace the current preview/selection
### 6.3 Inline editing
Inline editors:
- can be opened by clicking the row
- submit on `Enter`
- stop accidental room chat typing while the input is focused
---
## 7. Current limitations
- `Permanent furni vars` currently uses a fixed denominator (`60`) in the Nitro UI
- `@wired_timer` is still client-side, not a dedicated server timer
- `wired.tick.resolution` is kept for compatibility/documentation, but the current tick service uses `wired.tick.interval.ms`
- `wired.highscores.displaycount` is migrated/documented, but its usage should be validated in the current runtime path if highscore behaviour is changed later