Add sunrise Threads automation and improve capture and character interactions

This commit is contained in:
2026-11-02 03:28:58 +09:00
parent ff86bdb5b5
commit 850ac84ef7
34 changed files with 900 additions and 34 deletions
+15 -3
View File
@@ -1,7 +1,8 @@
import './style.css';
import { createDialogs } from './ui/dialogs.ts';
import { createScreenshot } from './ui/screenshot.ts';
import { loadSummitAssets } from './scene/summitAssets.ts';
import { calculateSun } from './astronomy/sunCalculator.ts';
import { calculateSun, sunriseAzimuth } from './astronomy/sunCalculator.ts';
import { createWorld } from './scene/world.ts';
import { createInformationPanel } from './ui/informationPanel.ts';
import { TimeController } from './ui/timeController.ts';
@@ -104,6 +105,7 @@ export async function start(options: StartOptions = {}) {
update();
}, coast, structures, reconstructSummit, summitGeometry, sheep);
const viewEvents = new AbortController();
const screenshot = createScreenshot(() => world.captureFrame());
document.querySelectorAll<HTMLButtonElement>('[data-look]').forEach(button => {
button.addEventListener('click', () => world.lookAtStructure(button.dataset.look!), { signal: viewEvents.signal });
});
@@ -151,6 +153,9 @@ export async function start(options: StartOptions = {}) {
update();
});
world.resetPosition();
const faceSunrise = () => world.lookAtSunrise(sunriseAzimuth(selectedDate, effectiveObserver));
faceSunrise();
let firstJoin = true;
const connectionStatus = document.getElementById('connection-status')!;
const modeButton = document.getElementById('session-mode') as HTMLButtonElement;
const retryButton = document.getElementById('retry-connection') as HTMLButtonElement;
@@ -166,7 +171,10 @@ export async function start(options: StartOptions = {}) {
nickname.value = `방문자-${visitorId.slice(-4)}`;
const multiplayer = createMultiplayerClient({
readPlayer: () => world.readPlayer(),
joined: player => world.applyPlayer(player),
joined: player => {
world.applyPlayer(player);
if (firstJoin) { faceSunrise(); firstJoin = false; }
},
correction: player => world.applyPlayer(player),
snapshot: (state, selfId) => world.synchronizePlayers(state.players, selfId),
weather: state => { if (sharedMode) applyWeather(state); },
@@ -230,9 +238,13 @@ export async function start(options: StartOptions = {}) {
document.querySelector<HTMLFieldSetElement>('#time-controls')!.disabled = false;
window.addEventListener('pagehide', (event) => {
multiplayer.disconnect();
if (!event.persisted) { dialogs.dispose(); viewEvents.abort(); height.dispose(); time.dispose(); weather.dispose(); multiplayer.dispose(); world.dispose(); }
if (!event.persisted) { screenshot.dispose(); dialogs.dispose(); viewEvents.abort(); height.dispose(); time.dispose(); weather.dispose(); multiplayer.dispose(); world.dispose(); }
});
window.addEventListener('pageshow', event => { if (event.persisted && sharedMode) join(); });
if (query.get('capture') === 'threads' && !sharedMode) {
const { installThreadsCapture } = await import('./ui/threadsCapture.ts');
installThreadsCapture(effectiveObserver, world);
}
options.ready?.();
} catch (error) {
status.textContent = '지형을 불러오지 못했습니다';