@dcl-regenesislabs/web-editor 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/editor.css +1 -0
- package/editor.js +33891 -0
- package/package.json +8 -4
- package/prefabs/admin-tools/composite.json +77 -0
- package/prefabs/admin-tools/data.json +28 -0
- package/prefabs/admin-tools/icons/admin-panel-control-button.png +0 -0
- package/prefabs/admin-tools/icons/admin-panel-moderation-control-button.png +0 -0
- package/prefabs/admin-tools/icons/admin-panel-rewards-control-button.png +0 -0
- package/prefabs/admin-tools/icons/admin-panel-smart-item-control-button.png +0 -0
- package/prefabs/admin-tools/icons/admin-panel-text-announcement-control-button.png +0 -0
- package/prefabs/admin-tools/icons/admin-panel-video-control-button.png +0 -0
- package/prefabs/admin-tools/icons/admin-tool-background.png +0 -0
- package/prefabs/admin-tools/icons/announcements/text-announcement-chat-message.png +0 -0
- package/prefabs/admin-tools/icons/announcements/text-announcement-check.png +0 -0
- package/prefabs/admin-tools/icons/announcements/text-announcement-close-button.png +0 -0
- package/prefabs/admin-tools/icons/moderation/admin-panel-verified-user.png +0 -0
- package/prefabs/admin-tools/icons/moderation/ban.png +0 -0
- package/prefabs/admin-tools/icons/moderation/chevron-back.png +0 -0
- package/prefabs/admin-tools/icons/moderation/chevron-forward.png +0 -0
- package/prefabs/admin-tools/icons/moderation/close.png +0 -0
- package/prefabs/admin-tools/icons/moderation/error.png +0 -0
- package/prefabs/admin-tools/icons/moderation/person-outline.png +0 -0
- package/prefabs/admin-tools/icons/moderation-control-icon.png +0 -0
- package/prefabs/admin-tools/icons/rewards/close.png +0 -0
- package/prefabs/admin-tools/icons/rewards/send.png +0 -0
- package/prefabs/admin-tools/icons/rewards-control.png +0 -0
- package/prefabs/admin-tools/icons/smart-item-control.png +0 -0
- package/prefabs/admin-tools/icons/text-announcement-control.png +0 -0
- package/prefabs/admin-tools/icons/video/chevron-down.png +0 -0
- package/prefabs/admin-tools/icons/video/chevron-up.png +0 -0
- package/prefabs/admin-tools/icons/video/copy-to-clipboard.png +0 -0
- package/prefabs/admin-tools/icons/video/error.png +0 -0
- package/prefabs/admin-tools/icons/video/eye-off.png +0 -0
- package/prefabs/admin-tools/icons/video/eye.png +0 -0
- package/prefabs/admin-tools/icons/video/help.png +0 -0
- package/prefabs/admin-tools/icons/video/info.png +0 -0
- package/prefabs/admin-tools/icons/video/person-outline.png +0 -0
- package/prefabs/admin-tools/icons/video/star.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-dcl-cast.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-live.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-loop.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-mute.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-pause-button.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-play-button.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-video-icon.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-volume-minus-button.png +0 -0
- package/prefabs/admin-tools/icons/video/video-control-volume-plus-button.png +0 -0
- package/prefabs/admin-tools/icons/video-control.png +0 -0
- package/prefabs/admin-tools/scripts/actions.ts +206 -0
- package/prefabs/admin-tools/scripts/admin.tsx +253 -0
- package/prefabs/admin-tools/scripts/api.ts +125 -0
- package/prefabs/admin-tools/scripts/components.ts +190 -0
- package/prefabs/admin-tools/scripts/icons.ts +53 -0
- package/prefabs/admin-tools/scripts/message-bus.ts +297 -0
- package/prefabs/admin-tools/scripts/state.ts +69 -0
- package/prefabs/admin-tools/scripts/tabs/Moderation.tsx +155 -0
- package/prefabs/admin-tools/scripts/tabs/Rewards.tsx +136 -0
- package/prefabs/admin-tools/scripts/tabs/SmartItemActions.tsx +167 -0
- package/prefabs/admin-tools/scripts/tabs/TextAnnouncements.tsx +195 -0
- package/prefabs/admin-tools/scripts/tabs/VideoControl.tsx +156 -0
- package/prefabs/admin-tools/scripts/tabs/announcements/Overlay.tsx +94 -0
- package/prefabs/admin-tools/scripts/tabs/announcements/icons.ts +15 -0
- package/prefabs/admin-tools/scripts/tabs/announcements/state.ts +71 -0
- package/prefabs/admin-tools/scripts/tabs/announcements/ui.tsx +37 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/AddUserInput.tsx +184 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/RemoveAdminConfirmation.tsx +93 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/UsersList.tsx +228 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/api.ts +35 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/icons.ts +23 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/kick.ts +95 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/state.ts +69 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/ui.tsx +172 -0
- package/prefabs/admin-tools/scripts/tabs/moderation/utils.ts +88 -0
- package/prefabs/admin-tools/scripts/tabs/rewards/Button.tsx +52 -0
- package/prefabs/admin-tools/scripts/tabs/rewards/Captcha.tsx +88 -0
- package/prefabs/admin-tools/scripts/tabs/rewards/api.ts +138 -0
- package/prefabs/admin-tools/scripts/tabs/rewards/claim.ts +99 -0
- package/prefabs/admin-tools/scripts/tabs/rewards/controller.ts +103 -0
- package/prefabs/admin-tools/scripts/tabs/rewards/icons.ts +13 -0
- package/prefabs/admin-tools/scripts/tabs/rewards/state.ts +32 -0
- package/prefabs/admin-tools/scripts/tabs/smart-items/selection.ts +90 -0
- package/prefabs/admin-tools/scripts/tabs/video/DclCast.tsx +226 -0
- package/prefabs/admin-tools/scripts/tabs/video/LiveStream.tsx +284 -0
- package/prefabs/admin-tools/scripts/tabs/video/SpeakerShowcase.tsx +112 -0
- package/prefabs/admin-tools/scripts/tabs/video/VideoUrl.tsx +107 -0
- package/prefabs/admin-tools/scripts/tabs/video/Volume.tsx +69 -0
- package/prefabs/admin-tools/scripts/tabs/video/api.ts +172 -0
- package/prefabs/admin-tools/scripts/tabs/video/controls.ts +108 -0
- package/prefabs/admin-tools/scripts/tabs/video/icons.ts +59 -0
- package/prefabs/admin-tools/scripts/tabs/video/speakers.ts +43 -0
- package/prefabs/admin-tools/scripts/tabs/video/state.ts +82 -0
- package/prefabs/admin-tools/scripts/tabs/video/ui.tsx +243 -0
- package/prefabs/admin-tools/scripts/types.ts +46 -0
- package/prefabs/admin-tools/scripts/ui.tsx +122 -0
- package/prefabs/admin-tools/thumbnail.png +0 -0
- package/prefabs/announcer/ai.md +76 -0
- package/prefabs/announcer/composite.json +31 -0
- package/prefabs/announcer/data.json +35 -0
- package/prefabs/announcer/scripts/announcer.tsx +79 -0
- package/prefabs/announcer/scripts/pure/toast.ts +30 -0
- package/prefabs/announcer/thumbnail.png +0 -0
- package/prefabs/black-chair/HighBackChair.glb +0 -0
- package/prefabs/black-chair/composite.json +74 -0
- package/prefabs/black-chair/data.json +30 -0
- package/prefabs/black-chair/scripts/seat.ts +191 -0
- package/prefabs/black-chair/thumbnail.png +0 -0
- package/prefabs/catalog.json +1 -0
- package/prefabs/classic-bench/Bench_01.glb +0 -0
- package/prefabs/classic-bench/composite.json +100 -0
- package/prefabs/classic-bench/data.json +34 -0
- package/prefabs/classic-bench/file1.png +0 -0
- package/prefabs/classic-bench/scripts/seat.ts +191 -0
- package/prefabs/classic-bench/thumbnail.png +0 -0
- package/prefabs/classic-bench-armrests/Bench 1.glb +0 -0
- package/prefabs/classic-bench-armrests/composite.json +100 -0
- package/prefabs/classic-bench-armrests/data.json +30 -0
- package/prefabs/classic-bench-armrests/scripts/seat.ts +191 -0
- package/prefabs/classic-bench-armrests/thumbnail.png +0 -0
- package/prefabs/classroom-chair/Chair_02.glb +0 -0
- package/prefabs/classroom-chair/composite.json +74 -0
- package/prefabs/classroom-chair/data.json +34 -0
- package/prefabs/classroom-chair/file1.png +0 -0
- package/prefabs/classroom-chair/scripts/seat.ts +191 -0
- package/prefabs/classroom-chair/thumbnail.png +0 -0
- package/prefabs/court-chair/Chair_Wood_01.glb +0 -0
- package/prefabs/court-chair/FanstasyPack_TX.png +0 -0
- package/prefabs/court-chair/composite.json +74 -0
- package/prefabs/court-chair/data.json +34 -0
- package/prefabs/court-chair/scripts/seat.ts +191 -0
- package/prefabs/court-chair/thumbnail.png +0 -0
- package/prefabs/curved-couch/CurvedCouch.glb +0 -0
- package/prefabs/curved-couch/composite.json +100 -0
- package/prefabs/curved-couch/data.json +30 -0
- package/prefabs/curved-couch/scripts/seat.ts +191 -0
- package/prefabs/curved-couch/thumbnail.png +0 -0
- package/prefabs/game-flow/ai.md +94 -0
- package/prefabs/game-flow/composite.json +45 -0
- package/prefabs/game-flow/data.json +27 -0
- package/prefabs/game-flow/scripts/game-flow.ts +168 -0
- package/prefabs/game-flow/scripts/pure/flow.ts +185 -0
- package/prefabs/game-flow/thumbnail.png +0 -0
- package/prefabs/health-respawn/ai.md +76 -0
- package/prefabs/health-respawn/composite.json +31 -0
- package/prefabs/health-respawn/data.json +38 -0
- package/prefabs/health-respawn/scripts/health-respawn.ts +98 -0
- package/prefabs/health-respawn/scripts/health.ts +22 -0
- package/prefabs/health-respawn/scripts/pure/health.ts +60 -0
- package/prefabs/health-respawn/thumbnail.png +0 -0
- package/prefabs/high-stool/HighStool.glb +0 -0
- package/prefabs/high-stool/composite.json +74 -0
- package/prefabs/high-stool/data.json +30 -0
- package/prefabs/high-stool/scripts/seat.ts +191 -0
- package/prefabs/high-stool/thumbnail.png +0 -0
- package/prefabs/large-couch/ThreeSeater_Couch.glb +0 -0
- package/prefabs/large-couch/composite.json +100 -0
- package/prefabs/large-couch/data.json +30 -0
- package/prefabs/large-couch/scripts/seat.ts +191 -0
- package/prefabs/large-couch/thumbnail.png +0 -0
- package/prefabs/leaderboard/ai.md +75 -0
- package/prefabs/leaderboard/board-panel.glb +0 -0
- package/prefabs/leaderboard/composite.json +82 -0
- package/prefabs/leaderboard/data.json +35 -0
- package/prefabs/leaderboard/scripts/leaderboard.ts +66 -0
- package/prefabs/leaderboard/scripts/pure/board.ts +71 -0
- package/prefabs/leaderboard/thumbnail.png +0 -0
- package/prefabs/loveseat/Couch_01.glb +0 -0
- package/prefabs/loveseat/composite.json +100 -0
- package/prefabs/loveseat/data.json +34 -0
- package/prefabs/loveseat/file1.png +0 -0
- package/prefabs/loveseat/scripts/seat.ts +191 -0
- package/prefabs/loveseat/thumbnail.png +0 -0
- package/prefabs/modern-sofa/ModernSofa.glb +0 -0
- package/prefabs/modern-sofa/composite.json +100 -0
- package/prefabs/modern-sofa/data.json +30 -0
- package/prefabs/modern-sofa/scripts/seat.ts +191 -0
- package/prefabs/modern-sofa/thumbnail.png +0 -0
- package/prefabs/outdoor-chair/Chair_07.glb +0 -0
- package/prefabs/outdoor-chair/composite.json +74 -0
- package/prefabs/outdoor-chair/data.json +34 -0
- package/prefabs/outdoor-chair/file1.png +0 -0
- package/prefabs/outdoor-chair/scripts/seat.ts +191 -0
- package/prefabs/outdoor-chair/thumbnail.png +0 -0
- package/prefabs/rustic-bench/Bench_01.glb +0 -0
- package/prefabs/rustic-bench/PiratesPack_TX.png.png +0 -0
- package/prefabs/rustic-bench/composite.json +100 -0
- package/prefabs/rustic-bench/data.json +34 -0
- package/prefabs/rustic-bench/scripts/seat.ts +191 -0
- package/prefabs/rustic-bench/thumbnail.png +0 -0
- package/prefabs/rustic-round-stool/Chairwood_01.glb +0 -0
- package/prefabs/rustic-round-stool/PiratesPack_TX.png.png +0 -0
- package/prefabs/rustic-round-stool/composite.json +74 -0
- package/prefabs/rustic-round-stool/data.json +34 -0
- package/prefabs/rustic-round-stool/scripts/seat.ts +191 -0
- package/prefabs/rustic-round-stool/thumbnail.png +0 -0
- package/prefabs/rustic-square-stool/Chairwood_02.glb +0 -0
- package/prefabs/rustic-square-stool/PiratesPack_TX.png.png +0 -0
- package/prefabs/rustic-square-stool/composite.json +74 -0
- package/prefabs/rustic-square-stool/data.json +34 -0
- package/prefabs/rustic-square-stool/scripts/seat.ts +191 -0
- package/prefabs/rustic-square-stool/thumbnail.png +0 -0
- package/prefabs/server-clock/ai.md +67 -0
- package/prefabs/server-clock/composite.json +45 -0
- package/prefabs/server-clock/data.json +24 -0
- package/prefabs/server-clock/scripts/clock-hud.tsx +55 -0
- package/prefabs/server-clock/scripts/server-clock.ts +71 -0
- package/prefabs/server-clock/thumbnail.png +0 -0
- package/prefabs/simple-chair/Chair_03.glb +0 -0
- package/prefabs/simple-chair/composite.json +74 -0
- package/prefabs/simple-chair/data.json +34 -0
- package/prefabs/simple-chair/file1.png +0 -0
- package/prefabs/simple-chair/scripts/seat.ts +191 -0
- package/prefabs/simple-chair/thumbnail.png +0 -0
- package/prefabs/sit-spot/composite.json +45 -0
- package/prefabs/sit-spot/data.json +30 -0
- package/prefabs/sit-spot/scripts/seat.ts +191 -0
- package/prefabs/sit-spot/thumbnail.png +0 -0
- package/prefabs/sit-spot-edge/composite.json +42 -0
- package/prefabs/sit-spot-edge/data.json +32 -0
- package/prefabs/sit-spot-edge/emotes/Sit_Edge1_emote.glb +0 -0
- package/prefabs/sit-spot-edge/emotes/Sit_Edge2_emote.glb +0 -0
- package/prefabs/sit-spot-edge/scripts/seat.ts +191 -0
- package/prefabs/sit-spot-edge/thumbnail.png +0 -0
- package/prefabs/small-couch/TwoSeater_Couch.glb +0 -0
- package/prefabs/small-couch/composite.json +100 -0
- package/prefabs/small-couch/data.json +30 -0
- package/prefabs/small-couch/scripts/seat.ts +191 -0
- package/prefabs/small-couch/thumbnail.png +0 -0
- package/prefabs/spawner/ai.md +109 -0
- package/prefabs/spawner/composite.json +73 -0
- package/prefabs/spawner/data.json +22 -0
- package/prefabs/spawner/scripts/spawner.ts +380 -0
- package/prefabs/spawner/thumbnail.png +0 -0
- package/prefabs/steampunk-bench/Steampunk Bench.glb +0 -0
- package/prefabs/steampunk-bench/composite.json +100 -0
- package/prefabs/steampunk-bench/data.json +30 -0
- package/prefabs/steampunk-bench/scripts/seat.ts +191 -0
- package/prefabs/steampunk-bench/thumbnail.png +0 -0
- package/prefabs/steampunk-chair/Steampunk Chair.glb +0 -0
- package/prefabs/steampunk-chair/composite.json +74 -0
- package/prefabs/steampunk-chair/data.json +30 -0
- package/prefabs/steampunk-chair/scripts/seat.ts +191 -0
- package/prefabs/steampunk-chair/thumbnail.png +0 -0
- package/prefabs/tall-stool/Stool_D.glb +0 -0
- package/prefabs/tall-stool/composite.json +74 -0
- package/prefabs/tall-stool/data.json +30 -0
- package/prefabs/tall-stool/scripts/seat.ts +191 -0
- package/prefabs/tall-stool/thumbnail.png +0 -0
- package/prefabs/trigger-zone/ai.md +115 -0
- package/prefabs/trigger-zone/composite.json +52 -0
- package/prefabs/trigger-zone/data.json +31 -0
- package/prefabs/trigger-zone/scripts/trigger-zone.ts +89 -0
- package/prefabs/trigger-zone/thumbnail.png +0 -0
- package/prefabs/video-screen/composite.json +98 -0
- package/prefabs/video-screen/data.json +21 -0
- package/prefabs/video-screen/thumbnail.png +0 -0
- package/prefabs/video-screen/video_player.glb +0 -0
- package/prefabs/wooden-chair/Chair 1.glb +0 -0
- package/prefabs/wooden-chair/composite.json +74 -0
- package/prefabs/wooden-chair/data.json +30 -0
- package/prefabs/wooden-chair/scripts/seat.ts +191 -0
- package/prefabs/wooden-chair/thumbnail.png +0 -0
- package/prefabs/wooden-chair-armrests/Chair 3.glb +0 -0
- package/prefabs/wooden-chair-armrests/composite.json +74 -0
- package/prefabs/wooden-chair-armrests/data.json +30 -0
- package/prefabs/wooden-chair-armrests/scripts/seat.ts +191 -0
- package/prefabs/wooden-chair-armrests/thumbnail.png +0 -0
- package/scene/about +17 -0
- package/scene/bafkreias2w4xuqaic6sdcvblrisayi6xg7drfowzpt5ubjkmrk3mx6czc4 +1 -0
- package/scene/bafkreiby2gmthtauf7cckttphmhpecsueyypi2hzlke4lcodg7fm4cm2sq +23 -0
- package/scene/bafkreidhwqwajqk4nsuffef5fkdrgmp5ql6vnn2knpqsuqalyosv5o6lk4 +1 -0
- package/scene/bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku +0 -0
- package/scene/bafybeihw3xlbff4sf5sc3kvmlmlwf2visnty5lfymawlunzt5vrkp5fd7u +90 -0
- package/web-build/esbuild.wasm +0 -0
- package/web-build/index.js +3 -0
- package/web-build/sdk-snapshot.json +1 -0
- package/web-build/worker.js +701 -0
- package/README.md +0 -3
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// Sit on this seat: click a sit spot -> the avatar is placed on it facing forward
|
|
2
|
+
// and a looping sitting emote plays; moving cancels the emote engine-side (the
|
|
3
|
+
// same mechanism the Creator Hub's seat smart items and Genesis Plaza use — no
|
|
4
|
+
// avatar attach). Spots are child entities named "Sit Spot…" carrying only a
|
|
5
|
+
// Transform; this script gives them their collider and pointer event at runtime.
|
|
6
|
+
// With no such children (the standalone Sit Spot prefab), the entity itself is
|
|
7
|
+
// the spot.
|
|
8
|
+
import {
|
|
9
|
+
ColliderLayer,
|
|
10
|
+
InputAction,
|
|
11
|
+
Material,
|
|
12
|
+
MeshCollider,
|
|
13
|
+
MeshRenderer,
|
|
14
|
+
Schemas,
|
|
15
|
+
Transform,
|
|
16
|
+
VisibilityComponent,
|
|
17
|
+
engine,
|
|
18
|
+
pointerEventsSystem,
|
|
19
|
+
type Entity,
|
|
20
|
+
type LastWriteWinElementSetComponentDefinition
|
|
21
|
+
} from '@dcl/sdk/ecs'
|
|
22
|
+
import { Quaternion, Vector3 } from '@dcl/sdk/math'
|
|
23
|
+
import { isServer } from '@dcl/sdk/network'
|
|
24
|
+
import { movePlayerTo, triggerEmote, triggerSceneEmote } from '~system/RestrictedActions'
|
|
25
|
+
|
|
26
|
+
const SPOT_NAME_PREFIX = 'sit spot'
|
|
27
|
+
const HOVER_TEXT = 'Sit Here'
|
|
28
|
+
const MAX_DISTANCE = 6
|
|
29
|
+
const EMOTE_DELAY_S = 0.25
|
|
30
|
+
const SITTING_EMOTES = ['sittingChair1', 'sittingChair2']
|
|
31
|
+
// emote .glb files bundled in this prefab's folder (Genesis Plaza-style custom
|
|
32
|
+
// poses, played via triggerSceneEmote); empty = the predefined chair emotes
|
|
33
|
+
const SCENE_EMOTES: string[] = []
|
|
34
|
+
|
|
35
|
+
// the Plaza-style "you can sit here" hint: a small glowing dot floating over
|
|
36
|
+
// each free spot, pulsing gently, shown only to nearby players
|
|
37
|
+
const DOT_VISIBLE_DIST = 10
|
|
38
|
+
const DOT_OCCUPIED_DIST = 0.9
|
|
39
|
+
const DOT_HEIGHT = 0.55
|
|
40
|
+
const DOT_SIZE = 0.09
|
|
41
|
+
const DOT_PULSE = 0.25
|
|
42
|
+
|
|
43
|
+
type NameValue = { value: string }
|
|
44
|
+
type NameComponent = LastWriteWinElementSetComponentDefinition<NameValue>
|
|
45
|
+
|
|
46
|
+
// Every placed seat prefab bundles its own copy of this script (prefab folders are
|
|
47
|
+
// self-contained), so the component may already be defined by a sibling copy.
|
|
48
|
+
function nameComponent(): NameComponent {
|
|
49
|
+
const existing = engine.getComponentOrNull('core-schema::Name')
|
|
50
|
+
if (existing !== null) return existing as NameComponent
|
|
51
|
+
return engine.defineComponent('core-schema::Name', { value: Schemas.String })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function isSpotName(name: unknown): boolean {
|
|
55
|
+
return typeof name === 'string' && name.toLowerCase().startsWith(SPOT_NAME_PREFIX)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function sceneRelativeTransform(entity: Entity): { position: Vector3; rotation: Quaternion } {
|
|
59
|
+
const chain: Entity[] = []
|
|
60
|
+
let cursor = entity
|
|
61
|
+
while (cursor !== engine.RootEntity && chain.length < 32) {
|
|
62
|
+
chain.push(cursor)
|
|
63
|
+
const t = Transform.getOrNull(cursor)
|
|
64
|
+
if (t === null) break
|
|
65
|
+
cursor = t.parent ?? engine.RootEntity
|
|
66
|
+
}
|
|
67
|
+
let position = Vector3.Zero()
|
|
68
|
+
let rotation = Quaternion.Identity()
|
|
69
|
+
let scale = Vector3.One()
|
|
70
|
+
for (const link of chain.reverse()) {
|
|
71
|
+
const t = Transform.getOrNull(link)
|
|
72
|
+
if (t === null) continue
|
|
73
|
+
const local = Vector3.create(
|
|
74
|
+
t.position.x * scale.x,
|
|
75
|
+
t.position.y * scale.y,
|
|
76
|
+
t.position.z * scale.z
|
|
77
|
+
)
|
|
78
|
+
position = Vector3.add(position, Vector3.rotate(local, rotation))
|
|
79
|
+
rotation = Quaternion.multiply(rotation, t.rotation)
|
|
80
|
+
scale = Vector3.create(scale.x * t.scale.x, scale.y * t.scale.y, scale.z * t.scale.z)
|
|
81
|
+
}
|
|
82
|
+
return { position, rotation }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export class Seat {
|
|
86
|
+
private emoteIn = 0
|
|
87
|
+
private time = 0
|
|
88
|
+
private dots: Array<{ spot: Entity; dot: Entity; visible: boolean }> = []
|
|
89
|
+
|
|
90
|
+
constructor(
|
|
91
|
+
public src: string,
|
|
92
|
+
public entity: Entity
|
|
93
|
+
) {}
|
|
94
|
+
|
|
95
|
+
start(): void {
|
|
96
|
+
if (isServer()) { return }
|
|
97
|
+
const Name = nameComponent()
|
|
98
|
+
const spots: Entity[] = []
|
|
99
|
+
for (const [child, transform] of engine.getEntitiesWith(Transform)) {
|
|
100
|
+
if (transform.parent !== this.entity) continue
|
|
101
|
+
const name = Name.getOrNull(child)
|
|
102
|
+
if (name !== null && isSpotName(name.value)) spots.push(child)
|
|
103
|
+
}
|
|
104
|
+
if (spots.length === 0) spots.push(this.entity)
|
|
105
|
+
|
|
106
|
+
for (const spot of spots) {
|
|
107
|
+
MeshCollider.setBox(spot, ColliderLayer.CL_POINTER)
|
|
108
|
+
pointerEventsSystem.onPointerDown(
|
|
109
|
+
{
|
|
110
|
+
entity: spot,
|
|
111
|
+
opts: { button: InputAction.IA_POINTER, hoverText: HOVER_TEXT, maxDistance: MAX_DISTANCE }
|
|
112
|
+
},
|
|
113
|
+
() => this.sit(spot)
|
|
114
|
+
)
|
|
115
|
+
// no collider on the dot: clicks pass through to the spot beneath it
|
|
116
|
+
const dot = engine.addEntity()
|
|
117
|
+
Transform.create(dot, {
|
|
118
|
+
parent: spot,
|
|
119
|
+
position: Vector3.create(0, DOT_HEIGHT, 0),
|
|
120
|
+
scale: Vector3.create(DOT_SIZE, DOT_SIZE, DOT_SIZE)
|
|
121
|
+
})
|
|
122
|
+
MeshRenderer.setSphere(dot)
|
|
123
|
+
Material.setPbrMaterial(dot, {
|
|
124
|
+
albedoColor: { r: 1, g: 1, b: 1, a: 0.85 },
|
|
125
|
+
emissiveColor: { r: 1, g: 1, b: 1 },
|
|
126
|
+
emissiveIntensity: 2,
|
|
127
|
+
roughness: 1
|
|
128
|
+
})
|
|
129
|
+
VisibilityComponent.create(dot, { visible: false })
|
|
130
|
+
this.dots.push({ spot, dot, visible: false })
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
update(dt: number): void {
|
|
135
|
+
// The hint walks a transform chain per spot per frame, and a seat is placed
|
|
136
|
+
// by the dozen: without this the Multiplayer Server pays for every one.
|
|
137
|
+
if (isServer()) { return }
|
|
138
|
+
this.time += dt
|
|
139
|
+
this.updateDots()
|
|
140
|
+
if (this.emoteIn <= 0) return
|
|
141
|
+
this.emoteIn -= dt
|
|
142
|
+
if (this.emoteIn > 0) return
|
|
143
|
+
if (SCENE_EMOTES.length > 0) {
|
|
144
|
+
// src is the script's directory (custom/<slug>/scripts) — the emotes live
|
|
145
|
+
// one level up, in the placed prefab's own folder
|
|
146
|
+
const root = this.src.replace(/\/scripts\/?$/, '')
|
|
147
|
+
const emote = SCENE_EMOTES[Math.floor(Math.random() * SCENE_EMOTES.length)]
|
|
148
|
+
void triggerSceneEmote({ src: `${root}/${emote}`, loop: true })
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
const emote = SITTING_EMOTES[Math.floor(Math.random() * SITTING_EMOTES.length)]
|
|
152
|
+
void triggerEmote({ predefinedEmote: emote })
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private updateDots(): void {
|
|
156
|
+
const player = Transform.getOrNull(engine.PlayerEntity)?.position
|
|
157
|
+
const pulse = 1 + DOT_PULSE * Math.sin(this.time * 3)
|
|
158
|
+
for (const entry of this.dots) {
|
|
159
|
+
let visible = false
|
|
160
|
+
if (player !== undefined) {
|
|
161
|
+
const world = sceneRelativeTransform(entry.spot).position
|
|
162
|
+
const dist = Vector3.distance(player, world)
|
|
163
|
+
// hidden while someone (you) is on the spot — a glow over a seated
|
|
164
|
+
// avatar's head reads as a bug, not a hint
|
|
165
|
+
visible = dist < DOT_VISIBLE_DIST && dist > DOT_OCCUPIED_DIST
|
|
166
|
+
}
|
|
167
|
+
if (entry.visible !== visible) {
|
|
168
|
+
entry.visible = visible
|
|
169
|
+
VisibilityComponent.getMutable(entry.dot).visible = visible
|
|
170
|
+
}
|
|
171
|
+
if (visible) {
|
|
172
|
+
Transform.getMutable(entry.dot).scale = Vector3.create(
|
|
173
|
+
DOT_SIZE * pulse,
|
|
174
|
+
DOT_SIZE * pulse,
|
|
175
|
+
DOT_SIZE * pulse
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private sit(spot: Entity): void {
|
|
182
|
+
const world = sceneRelativeTransform(spot)
|
|
183
|
+
const forward = Vector3.rotate(Vector3.Forward(), world.rotation)
|
|
184
|
+
void movePlayerTo({
|
|
185
|
+
newRelativePosition: world.position,
|
|
186
|
+
avatarTarget: Vector3.add(world.position, forward)
|
|
187
|
+
})
|
|
188
|
+
// let the teleport settle before the emote starts, or the walk cancels it
|
|
189
|
+
this.emoteIn = EMOTE_DELAY_S
|
|
190
|
+
}
|
|
191
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"components": [
|
|
4
|
+
{
|
|
5
|
+
"name": "core::GltfContainer",
|
|
6
|
+
"data": {
|
|
7
|
+
"0": {
|
|
8
|
+
"json": {
|
|
9
|
+
"src": "{assetPath}/Bench 1.glb",
|
|
10
|
+
"visibleMeshesCollisionMask": 0,
|
|
11
|
+
"invisibleMeshesCollisionMask": 3
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "core-schema::Name",
|
|
18
|
+
"data": {
|
|
19
|
+
"0": {
|
|
20
|
+
"json": {
|
|
21
|
+
"value": "Classic Bench Armrests"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"513": {
|
|
25
|
+
"json": {
|
|
26
|
+
"value": "Sit Spot 1"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"514": {
|
|
30
|
+
"json": {
|
|
31
|
+
"value": "Sit Spot 2"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "core::Transform",
|
|
38
|
+
"data": {
|
|
39
|
+
"513": {
|
|
40
|
+
"json": {
|
|
41
|
+
"position": {
|
|
42
|
+
"x": 0.4673,
|
|
43
|
+
"y": 0,
|
|
44
|
+
"z": 0.2757
|
|
45
|
+
},
|
|
46
|
+
"rotation": {
|
|
47
|
+
"x": 0,
|
|
48
|
+
"y": 0.07845906913280487,
|
|
49
|
+
"z": 0,
|
|
50
|
+
"w": 0.9969173669815063
|
|
51
|
+
},
|
|
52
|
+
"scale": {
|
|
53
|
+
"x": 1,
|
|
54
|
+
"y": 1,
|
|
55
|
+
"z": 1
|
|
56
|
+
},
|
|
57
|
+
"parent": 0
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"514": {
|
|
61
|
+
"json": {
|
|
62
|
+
"position": {
|
|
63
|
+
"x": -0.4,
|
|
64
|
+
"y": 0,
|
|
65
|
+
"z": 0.28
|
|
66
|
+
},
|
|
67
|
+
"rotation": {
|
|
68
|
+
"x": 0,
|
|
69
|
+
"y": 0.07845909893512726,
|
|
70
|
+
"z": 0,
|
|
71
|
+
"w": 0.9969173073768616
|
|
72
|
+
},
|
|
73
|
+
"scale": {
|
|
74
|
+
"x": 1,
|
|
75
|
+
"y": 1,
|
|
76
|
+
"z": 1
|
|
77
|
+
},
|
|
78
|
+
"parent": 0
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "asset-packs::Script",
|
|
85
|
+
"data": {
|
|
86
|
+
"0": {
|
|
87
|
+
"json": {
|
|
88
|
+
"value": [
|
|
89
|
+
{
|
|
90
|
+
"path": "{assetPath}/scripts/seat.ts",
|
|
91
|
+
"priority": 0,
|
|
92
|
+
"layout": "{\"params\":{},\"actions\":[]}"
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "88e01dcc-b242-4815-90e3-72ff52c24f45",
|
|
3
|
+
"name": "Classic Bench Armrests",
|
|
4
|
+
"description": "A classic park bench with armrests, seating two. Players can sit on it.",
|
|
5
|
+
"category": "custom",
|
|
6
|
+
"tags": [
|
|
7
|
+
"seat",
|
|
8
|
+
"furniture",
|
|
9
|
+
"sit"
|
|
10
|
+
],
|
|
11
|
+
"version": "1.1.0",
|
|
12
|
+
"changelog": [
|
|
13
|
+
{
|
|
14
|
+
"version": "1.1.0",
|
|
15
|
+
"notes": "The seat no longer runs on the Multiplayer Server, where it was walking every sit spot's transform chain each frame for nobody to see."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"version": "1.0.0",
|
|
19
|
+
"notes": "Initial release"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"origin": {
|
|
23
|
+
"source": "builtin"
|
|
24
|
+
},
|
|
25
|
+
"requiredPermissions": [
|
|
26
|
+
"ALLOW_TO_MOVE_PLAYER_INSIDE_SCENE",
|
|
27
|
+
"ALLOW_TO_TRIGGER_AVATAR_EMOTE"
|
|
28
|
+
],
|
|
29
|
+
"group": "Seats"
|
|
30
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// Sit on this seat: click a sit spot -> the avatar is placed on it facing forward
|
|
2
|
+
// and a looping sitting emote plays; moving cancels the emote engine-side (the
|
|
3
|
+
// same mechanism the Creator Hub's seat smart items and Genesis Plaza use — no
|
|
4
|
+
// avatar attach). Spots are child entities named "Sit Spot…" carrying only a
|
|
5
|
+
// Transform; this script gives them their collider and pointer event at runtime.
|
|
6
|
+
// With no such children (the standalone Sit Spot prefab), the entity itself is
|
|
7
|
+
// the spot.
|
|
8
|
+
import {
|
|
9
|
+
ColliderLayer,
|
|
10
|
+
InputAction,
|
|
11
|
+
Material,
|
|
12
|
+
MeshCollider,
|
|
13
|
+
MeshRenderer,
|
|
14
|
+
Schemas,
|
|
15
|
+
Transform,
|
|
16
|
+
VisibilityComponent,
|
|
17
|
+
engine,
|
|
18
|
+
pointerEventsSystem,
|
|
19
|
+
type Entity,
|
|
20
|
+
type LastWriteWinElementSetComponentDefinition
|
|
21
|
+
} from '@dcl/sdk/ecs'
|
|
22
|
+
import { Quaternion, Vector3 } from '@dcl/sdk/math'
|
|
23
|
+
import { isServer } from '@dcl/sdk/network'
|
|
24
|
+
import { movePlayerTo, triggerEmote, triggerSceneEmote } from '~system/RestrictedActions'
|
|
25
|
+
|
|
26
|
+
const SPOT_NAME_PREFIX = 'sit spot'
|
|
27
|
+
const HOVER_TEXT = 'Sit Here'
|
|
28
|
+
const MAX_DISTANCE = 6
|
|
29
|
+
const EMOTE_DELAY_S = 0.25
|
|
30
|
+
const SITTING_EMOTES = ['sittingChair1', 'sittingChair2']
|
|
31
|
+
// emote .glb files bundled in this prefab's folder (Genesis Plaza-style custom
|
|
32
|
+
// poses, played via triggerSceneEmote); empty = the predefined chair emotes
|
|
33
|
+
const SCENE_EMOTES: string[] = []
|
|
34
|
+
|
|
35
|
+
// the Plaza-style "you can sit here" hint: a small glowing dot floating over
|
|
36
|
+
// each free spot, pulsing gently, shown only to nearby players
|
|
37
|
+
const DOT_VISIBLE_DIST = 10
|
|
38
|
+
const DOT_OCCUPIED_DIST = 0.9
|
|
39
|
+
const DOT_HEIGHT = 0.55
|
|
40
|
+
const DOT_SIZE = 0.09
|
|
41
|
+
const DOT_PULSE = 0.25
|
|
42
|
+
|
|
43
|
+
type NameValue = { value: string }
|
|
44
|
+
type NameComponent = LastWriteWinElementSetComponentDefinition<NameValue>
|
|
45
|
+
|
|
46
|
+
// Every placed seat prefab bundles its own copy of this script (prefab folders are
|
|
47
|
+
// self-contained), so the component may already be defined by a sibling copy.
|
|
48
|
+
function nameComponent(): NameComponent {
|
|
49
|
+
const existing = engine.getComponentOrNull('core-schema::Name')
|
|
50
|
+
if (existing !== null) return existing as NameComponent
|
|
51
|
+
return engine.defineComponent('core-schema::Name', { value: Schemas.String })
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function isSpotName(name: unknown): boolean {
|
|
55
|
+
return typeof name === 'string' && name.toLowerCase().startsWith(SPOT_NAME_PREFIX)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function sceneRelativeTransform(entity: Entity): { position: Vector3; rotation: Quaternion } {
|
|
59
|
+
const chain: Entity[] = []
|
|
60
|
+
let cursor = entity
|
|
61
|
+
while (cursor !== engine.RootEntity && chain.length < 32) {
|
|
62
|
+
chain.push(cursor)
|
|
63
|
+
const t = Transform.getOrNull(cursor)
|
|
64
|
+
if (t === null) break
|
|
65
|
+
cursor = t.parent ?? engine.RootEntity
|
|
66
|
+
}
|
|
67
|
+
let position = Vector3.Zero()
|
|
68
|
+
let rotation = Quaternion.Identity()
|
|
69
|
+
let scale = Vector3.One()
|
|
70
|
+
for (const link of chain.reverse()) {
|
|
71
|
+
const t = Transform.getOrNull(link)
|
|
72
|
+
if (t === null) continue
|
|
73
|
+
const local = Vector3.create(
|
|
74
|
+
t.position.x * scale.x,
|
|
75
|
+
t.position.y * scale.y,
|
|
76
|
+
t.position.z * scale.z
|
|
77
|
+
)
|
|
78
|
+
position = Vector3.add(position, Vector3.rotate(local, rotation))
|
|
79
|
+
rotation = Quaternion.multiply(rotation, t.rotation)
|
|
80
|
+
scale = Vector3.create(scale.x * t.scale.x, scale.y * t.scale.y, scale.z * t.scale.z)
|
|
81
|
+
}
|
|
82
|
+
return { position, rotation }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export class Seat {
|
|
86
|
+
private emoteIn = 0
|
|
87
|
+
private time = 0
|
|
88
|
+
private dots: Array<{ spot: Entity; dot: Entity; visible: boolean }> = []
|
|
89
|
+
|
|
90
|
+
constructor(
|
|
91
|
+
public src: string,
|
|
92
|
+
public entity: Entity
|
|
93
|
+
) {}
|
|
94
|
+
|
|
95
|
+
start(): void {
|
|
96
|
+
if (isServer()) { return }
|
|
97
|
+
const Name = nameComponent()
|
|
98
|
+
const spots: Entity[] = []
|
|
99
|
+
for (const [child, transform] of engine.getEntitiesWith(Transform)) {
|
|
100
|
+
if (transform.parent !== this.entity) continue
|
|
101
|
+
const name = Name.getOrNull(child)
|
|
102
|
+
if (name !== null && isSpotName(name.value)) spots.push(child)
|
|
103
|
+
}
|
|
104
|
+
if (spots.length === 0) spots.push(this.entity)
|
|
105
|
+
|
|
106
|
+
for (const spot of spots) {
|
|
107
|
+
MeshCollider.setBox(spot, ColliderLayer.CL_POINTER)
|
|
108
|
+
pointerEventsSystem.onPointerDown(
|
|
109
|
+
{
|
|
110
|
+
entity: spot,
|
|
111
|
+
opts: { button: InputAction.IA_POINTER, hoverText: HOVER_TEXT, maxDistance: MAX_DISTANCE }
|
|
112
|
+
},
|
|
113
|
+
() => this.sit(spot)
|
|
114
|
+
)
|
|
115
|
+
// no collider on the dot: clicks pass through to the spot beneath it
|
|
116
|
+
const dot = engine.addEntity()
|
|
117
|
+
Transform.create(dot, {
|
|
118
|
+
parent: spot,
|
|
119
|
+
position: Vector3.create(0, DOT_HEIGHT, 0),
|
|
120
|
+
scale: Vector3.create(DOT_SIZE, DOT_SIZE, DOT_SIZE)
|
|
121
|
+
})
|
|
122
|
+
MeshRenderer.setSphere(dot)
|
|
123
|
+
Material.setPbrMaterial(dot, {
|
|
124
|
+
albedoColor: { r: 1, g: 1, b: 1, a: 0.85 },
|
|
125
|
+
emissiveColor: { r: 1, g: 1, b: 1 },
|
|
126
|
+
emissiveIntensity: 2,
|
|
127
|
+
roughness: 1
|
|
128
|
+
})
|
|
129
|
+
VisibilityComponent.create(dot, { visible: false })
|
|
130
|
+
this.dots.push({ spot, dot, visible: false })
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
update(dt: number): void {
|
|
135
|
+
// The hint walks a transform chain per spot per frame, and a seat is placed
|
|
136
|
+
// by the dozen: without this the Multiplayer Server pays for every one.
|
|
137
|
+
if (isServer()) { return }
|
|
138
|
+
this.time += dt
|
|
139
|
+
this.updateDots()
|
|
140
|
+
if (this.emoteIn <= 0) return
|
|
141
|
+
this.emoteIn -= dt
|
|
142
|
+
if (this.emoteIn > 0) return
|
|
143
|
+
if (SCENE_EMOTES.length > 0) {
|
|
144
|
+
// src is the script's directory (custom/<slug>/scripts) — the emotes live
|
|
145
|
+
// one level up, in the placed prefab's own folder
|
|
146
|
+
const root = this.src.replace(/\/scripts\/?$/, '')
|
|
147
|
+
const emote = SCENE_EMOTES[Math.floor(Math.random() * SCENE_EMOTES.length)]
|
|
148
|
+
void triggerSceneEmote({ src: `${root}/${emote}`, loop: true })
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
const emote = SITTING_EMOTES[Math.floor(Math.random() * SITTING_EMOTES.length)]
|
|
152
|
+
void triggerEmote({ predefinedEmote: emote })
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private updateDots(): void {
|
|
156
|
+
const player = Transform.getOrNull(engine.PlayerEntity)?.position
|
|
157
|
+
const pulse = 1 + DOT_PULSE * Math.sin(this.time * 3)
|
|
158
|
+
for (const entry of this.dots) {
|
|
159
|
+
let visible = false
|
|
160
|
+
if (player !== undefined) {
|
|
161
|
+
const world = sceneRelativeTransform(entry.spot).position
|
|
162
|
+
const dist = Vector3.distance(player, world)
|
|
163
|
+
// hidden while someone (you) is on the spot — a glow over a seated
|
|
164
|
+
// avatar's head reads as a bug, not a hint
|
|
165
|
+
visible = dist < DOT_VISIBLE_DIST && dist > DOT_OCCUPIED_DIST
|
|
166
|
+
}
|
|
167
|
+
if (entry.visible !== visible) {
|
|
168
|
+
entry.visible = visible
|
|
169
|
+
VisibilityComponent.getMutable(entry.dot).visible = visible
|
|
170
|
+
}
|
|
171
|
+
if (visible) {
|
|
172
|
+
Transform.getMutable(entry.dot).scale = Vector3.create(
|
|
173
|
+
DOT_SIZE * pulse,
|
|
174
|
+
DOT_SIZE * pulse,
|
|
175
|
+
DOT_SIZE * pulse
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private sit(spot: Entity): void {
|
|
182
|
+
const world = sceneRelativeTransform(spot)
|
|
183
|
+
const forward = Vector3.rotate(Vector3.Forward(), world.rotation)
|
|
184
|
+
void movePlayerTo({
|
|
185
|
+
newRelativePosition: world.position,
|
|
186
|
+
avatarTarget: Vector3.add(world.position, forward)
|
|
187
|
+
})
|
|
188
|
+
// let the teleport settle before the emote starts, or the walk cancels it
|
|
189
|
+
this.emoteIn = EMOTE_DELAY_S
|
|
190
|
+
}
|
|
191
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"components": [
|
|
4
|
+
{
|
|
5
|
+
"name": "core::GltfContainer",
|
|
6
|
+
"data": {
|
|
7
|
+
"0": {
|
|
8
|
+
"json": {
|
|
9
|
+
"src": "{assetPath}/Chair_02.glb",
|
|
10
|
+
"visibleMeshesCollisionMask": 0,
|
|
11
|
+
"invisibleMeshesCollisionMask": 3
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "core-schema::Name",
|
|
18
|
+
"data": {
|
|
19
|
+
"0": {
|
|
20
|
+
"json": {
|
|
21
|
+
"value": "Classroom Chair"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"513": {
|
|
25
|
+
"json": {
|
|
26
|
+
"value": "Sit Spot"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "core::Transform",
|
|
33
|
+
"data": {
|
|
34
|
+
"513": {
|
|
35
|
+
"json": {
|
|
36
|
+
"position": {
|
|
37
|
+
"x": -0.32,
|
|
38
|
+
"y": 0.15,
|
|
39
|
+
"z": 0
|
|
40
|
+
},
|
|
41
|
+
"scale": {
|
|
42
|
+
"x": 1,
|
|
43
|
+
"y": 1,
|
|
44
|
+
"z": 1
|
|
45
|
+
},
|
|
46
|
+
"rotation": {
|
|
47
|
+
"x": 0,
|
|
48
|
+
"y": 0.7071067811865476,
|
|
49
|
+
"z": 0,
|
|
50
|
+
"w": -0.7071067811865475
|
|
51
|
+
},
|
|
52
|
+
"parent": 0
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "asset-packs::Script",
|
|
59
|
+
"data": {
|
|
60
|
+
"0": {
|
|
61
|
+
"json": {
|
|
62
|
+
"value": [
|
|
63
|
+
{
|
|
64
|
+
"path": "{assetPath}/scripts/seat.ts",
|
|
65
|
+
"priority": 0,
|
|
66
|
+
"layout": "{\"params\":{},\"actions\":[]}"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "cacd50dc-5861-4b71-83ee-83cb23fea9e4",
|
|
3
|
+
"name": "Classroom Chair",
|
|
4
|
+
"description": "A moulded classroom chair. Players can sit on it.",
|
|
5
|
+
"category": "custom",
|
|
6
|
+
"tags": [
|
|
7
|
+
"seat",
|
|
8
|
+
"furniture",
|
|
9
|
+
"sit"
|
|
10
|
+
],
|
|
11
|
+
"version": "1.1.0",
|
|
12
|
+
"changelog": [
|
|
13
|
+
{
|
|
14
|
+
"version": "1.1.0",
|
|
15
|
+
"notes": "The seat no longer runs on the Multiplayer Server, where it was walking every sit spot's transform chain each frame for nobody to see."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"version": "1.0.1",
|
|
19
|
+
"notes": "Ships the model's texture, which was missing from the folder — without it the model rendered blank white in-world."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"version": "1.0.0",
|
|
23
|
+
"notes": "Initial release"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"origin": {
|
|
27
|
+
"source": "builtin"
|
|
28
|
+
},
|
|
29
|
+
"requiredPermissions": [
|
|
30
|
+
"ALLOW_TO_MOVE_PLAYER_INSIDE_SCENE",
|
|
31
|
+
"ALLOW_TO_TRIGGER_AVATAR_EMOTE"
|
|
32
|
+
],
|
|
33
|
+
"group": "Seats"
|
|
34
|
+
}
|
|
Binary file
|