@jgengine/core 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/LICENSE +661 -0
- package/README.md +11 -0
- package/dist/assets/spriteSheet.d.ts +46 -0
- package/dist/assets/spriteSheet.js +86 -0
- package/dist/combat/death.d.ts +61 -0
- package/dist/combat/death.js +61 -0
- package/dist/combat/effects.d.ts +61 -0
- package/dist/combat/effects.js +108 -0
- package/dist/combat/projectiles.d.ts +45 -0
- package/dist/combat/projectiles.js +156 -0
- package/dist/commands/commandRegistry.d.ts +23 -0
- package/dist/commands/commandRegistry.js +26 -0
- package/dist/economy/currency.d.ts +26 -0
- package/dist/economy/currency.js +28 -0
- package/dist/economy/wallet.d.ts +16 -0
- package/dist/economy/wallet.js +49 -0
- package/dist/game/defineGame.d.ts +41 -0
- package/dist/game/defineGame.js +7 -0
- package/dist/game/events.d.ts +87 -0
- package/dist/game/events.js +24 -0
- package/dist/game/feed.d.ts +19 -0
- package/dist/game/feed.js +47 -0
- package/dist/game/leaderboard.d.ts +46 -0
- package/dist/game/leaderboard.js +60 -0
- package/dist/game/loadout.d.ts +47 -0
- package/dist/game/loadout.js +36 -0
- package/dist/game/lootTable.d.ts +27 -0
- package/dist/game/lootTable.js +78 -0
- package/dist/game/playableGame.d.ts +55 -0
- package/dist/game/playableGame.js +1 -0
- package/dist/game/quest.d.ts +93 -0
- package/dist/game/quest.js +228 -0
- package/dist/game/social.d.ts +78 -0
- package/dist/game/social.js +227 -0
- package/dist/game/trade.d.ts +35 -0
- package/dist/game/trade.js +53 -0
- package/dist/game/unlocks.d.ts +13 -0
- package/dist/game/unlocks.js +34 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/input/actionBindings.d.ts +41 -0
- package/dist/input/actionBindings.js +115 -0
- package/dist/input/lookChannel.d.ts +29 -0
- package/dist/input/lookChannel.js +44 -0
- package/dist/input/touchGestures.d.ts +31 -0
- package/dist/input/touchGestures.js +72 -0
- package/dist/interaction/proximityPrompt.d.ts +51 -0
- package/dist/interaction/proximityPrompt.js +76 -0
- package/dist/inventory/inventoryModel.d.ts +57 -0
- package/dist/inventory/inventoryModel.js +208 -0
- package/dist/item/use.d.ts +25 -0
- package/dist/item/use.js +40 -0
- package/dist/item/weapon.d.ts +8 -0
- package/dist/item/weapon.js +18 -0
- package/dist/movement/avatarGait.d.ts +14 -0
- package/dist/movement/avatarGait.js +20 -0
- package/dist/movement/cameraRig.d.ts +15 -0
- package/dist/movement/cameraRig.js +43 -0
- package/dist/movement/movementModel.d.ts +96 -0
- package/dist/movement/movementModel.js +171 -0
- package/dist/movement/poseState.d.ts +23 -0
- package/dist/movement/poseState.js +61 -0
- package/dist/multiplayer/poseSyncGate.d.ts +18 -0
- package/dist/multiplayer/poseSyncGate.js +30 -0
- package/dist/multiplayer/presenceContract.d.ts +60 -0
- package/dist/multiplayer/presenceContract.js +19 -0
- package/dist/multiplayer/presenceModel.d.ts +60 -0
- package/dist/multiplayer/presenceModel.js +51 -0
- package/dist/runtime/adapter.d.ts +24 -0
- package/dist/runtime/adapter.js +12 -0
- package/dist/runtime/commandRunner.d.ts +15 -0
- package/dist/runtime/commandRunner.js +25 -0
- package/dist/runtime/gameContext.d.ts +138 -0
- package/dist/runtime/gameContext.js +371 -0
- package/dist/runtime/gameRuntime.d.ts +42 -0
- package/dist/runtime/gameRuntime.js +95 -0
- package/dist/runtime/hostPersistence.d.ts +105 -0
- package/dist/runtime/hostPersistence.js +117 -0
- package/dist/runtime/save.d.ts +9 -0
- package/dist/runtime/save.js +29 -0
- package/dist/runtime/snapshot.d.ts +87 -0
- package/dist/runtime/snapshot.js +75 -0
- package/dist/runtime/transport.d.ts +60 -0
- package/dist/runtime/transport.js +1 -0
- package/dist/scene/assetCatalog.d.ts +10 -0
- package/dist/scene/assetCatalog.js +17 -0
- package/dist/scene/assetPreload.d.ts +7 -0
- package/dist/scene/assetPreload.js +22 -0
- package/dist/scene/behaviors.d.ts +19 -0
- package/dist/scene/behaviors.js +18 -0
- package/dist/scene/entityStats.d.ts +38 -0
- package/dist/scene/entityStats.js +65 -0
- package/dist/scene/entityStore.d.ts +52 -0
- package/dist/scene/entityStore.js +84 -0
- package/dist/scene/objectStore.d.ts +28 -0
- package/dist/scene/objectStore.js +69 -0
- package/dist/scene/spatial.d.ts +34 -0
- package/dist/scene/spatial.js +96 -0
- package/dist/scene/targeting.d.ts +20 -0
- package/dist/scene/targeting.js +56 -0
- package/dist/stats/statModifiers.d.ts +18 -0
- package/dist/stats/statModifiers.js +56 -0
- package/dist/store/changeSignal.d.ts +7 -0
- package/dist/store/changeSignal.js +32 -0
- package/dist/store/engineStore.d.ts +22 -0
- package/dist/store/engineStore.js +50 -0
- package/dist/store/features.d.ts +10 -0
- package/dist/store/features.js +23 -0
- package/dist/store/observableKeyedStore.d.ts +10 -0
- package/dist/store/observableKeyedStore.js +42 -0
- package/dist/time/calendarClock.d.ts +17 -0
- package/dist/time/calendarClock.js +42 -0
- package/dist/time/gameClock.d.ts +9 -0
- package/dist/time/gameClock.js +20 -0
- package/dist/time/serverTick.d.ts +16 -0
- package/dist/time/serverTick.js +18 -0
- package/dist/world/features.d.ts +39 -0
- package/dist/world/features.js +15 -0
- package/package.json +32 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface GameTime {
|
|
2
|
+
year: number;
|
|
3
|
+
month: number;
|
|
4
|
+
monthName: string;
|
|
5
|
+
monthNameFull: string;
|
|
6
|
+
dayOfMonth: number;
|
|
7
|
+
hour: number;
|
|
8
|
+
minute: number;
|
|
9
|
+
second: number;
|
|
10
|
+
formattedDate: string;
|
|
11
|
+
formattedDateFull: string;
|
|
12
|
+
formattedTime: string;
|
|
13
|
+
formatted: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function computeGameTime(gameTimestamp: number): GameTime;
|
|
16
|
+
export declare function computeClientServerOffset(serverNow: number, clientNow: number): number;
|
|
17
|
+
export declare function getGameClockTimestamp(createdAt: number, serverNow: number, clientNow: number, gameTimeScale?: number): number;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getCurrentGameTimestamp, sanitizeGameTimeScale } from "@jgengine/core/time/gameClock";
|
|
2
|
+
const MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
3
|
+
const MONTH_NAMES_FULL = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
4
|
+
export function computeGameTime(gameTimestamp) {
|
|
5
|
+
const d = new Date(gameTimestamp);
|
|
6
|
+
const year = d.getFullYear();
|
|
7
|
+
const month = d.getMonth() + 1;
|
|
8
|
+
const monthName = MONTH_NAMES_SHORT[d.getMonth()] ?? "Jan";
|
|
9
|
+
const monthNameFull = MONTH_NAMES_FULL[d.getMonth()] ?? "January";
|
|
10
|
+
const dayOfMonth = d.getDate();
|
|
11
|
+
const hour = d.getHours();
|
|
12
|
+
const minute = d.getMinutes();
|
|
13
|
+
const second = d.getSeconds();
|
|
14
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
15
|
+
const hour12 = hour % 12 || 12;
|
|
16
|
+
const ampm = hour < 12 ? "AM" : "PM";
|
|
17
|
+
const formattedDate = `${monthName} ${dayOfMonth}, ${year}`;
|
|
18
|
+
const formattedDateFull = `${monthNameFull} ${dayOfMonth}, ${year}`;
|
|
19
|
+
const formattedTime = `${hour12}:${pad(minute)} ${ampm}`;
|
|
20
|
+
const formatted = `${formattedDate} ${formattedTime}`;
|
|
21
|
+
return {
|
|
22
|
+
year,
|
|
23
|
+
month,
|
|
24
|
+
monthName,
|
|
25
|
+
monthNameFull,
|
|
26
|
+
dayOfMonth,
|
|
27
|
+
hour,
|
|
28
|
+
minute,
|
|
29
|
+
second,
|
|
30
|
+
formattedDate,
|
|
31
|
+
formattedDateFull,
|
|
32
|
+
formattedTime,
|
|
33
|
+
formatted,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function computeClientServerOffset(serverNow, clientNow) {
|
|
37
|
+
return serverNow - clientNow;
|
|
38
|
+
}
|
|
39
|
+
export function getGameClockTimestamp(createdAt, serverNow, clientNow, gameTimeScale) {
|
|
40
|
+
const clientOffsetMs = computeClientServerOffset(serverNow, clientNow);
|
|
41
|
+
return getCurrentGameTimestamp(createdAt, clientNow + clientOffsetMs, sanitizeGameTimeScale(gameTimeScale));
|
|
42
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simulation clock: real time scaled into game time, plus the derived game-day counter.
|
|
3
|
+
*/
|
|
4
|
+
export declare const DEFAULT_TIME_SCALE = 24;
|
|
5
|
+
export declare const SECONDS_PER_GAME_DAY: number;
|
|
6
|
+
export declare function sanitizeGameTimeScale(timeScale?: number | null): number;
|
|
7
|
+
export declare function getScaledElapsedMs(createdAt: number, now: number, timeScale?: number | null): number;
|
|
8
|
+
export declare function getCurrentGameTimestamp(createdAt: number, now: number, timeScale?: number | null): number;
|
|
9
|
+
export declare function computeGameDay(createdAt: number, now?: number, timeScale?: number | null): number;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simulation clock: real time scaled into game time, plus the derived game-day counter.
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_TIME_SCALE = 24;
|
|
5
|
+
export const SECONDS_PER_GAME_DAY = 24 * 3600;
|
|
6
|
+
export function sanitizeGameTimeScale(timeScale) {
|
|
7
|
+
if (typeof timeScale !== "number" || !Number.isFinite(timeScale) || timeScale <= 0) {
|
|
8
|
+
return DEFAULT_TIME_SCALE;
|
|
9
|
+
}
|
|
10
|
+
return timeScale;
|
|
11
|
+
}
|
|
12
|
+
export function getScaledElapsedMs(createdAt, now, timeScale) {
|
|
13
|
+
return Math.max(0, Math.floor((now - createdAt) * sanitizeGameTimeScale(timeScale)));
|
|
14
|
+
}
|
|
15
|
+
export function getCurrentGameTimestamp(createdAt, now, timeScale) {
|
|
16
|
+
return createdAt + getScaledElapsedMs(createdAt, now, timeScale);
|
|
17
|
+
}
|
|
18
|
+
export function computeGameDay(createdAt, now = Date.now(), timeScale) {
|
|
19
|
+
return Math.floor(getScaledElapsedMs(createdAt, now, timeScale) / 1000 / SECONDS_PER_GAME_DAY);
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface TickSystemDefinition<TSystemId extends string = string> {
|
|
2
|
+
id: TSystemId;
|
|
3
|
+
/** Minimum real time between runs; the heartbeat fires the system on the first tick at or past it. */
|
|
4
|
+
intervalMs: number;
|
|
5
|
+
}
|
|
6
|
+
/** Last-run timestamp per system id. */
|
|
7
|
+
export type TickAnchors = Record<string, number>;
|
|
8
|
+
export interface ServerTickPlan<TSystemId extends string = string> {
|
|
9
|
+
due: TSystemId[];
|
|
10
|
+
anchors: TickAnchors;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Decides which systems a heartbeat should run. A system with no anchor runs immediately.
|
|
14
|
+
* Returned anchors carry only systems present in the pipeline, so removed systems clean up.
|
|
15
|
+
*/
|
|
16
|
+
export declare function planServerTick<TSystemId extends string>(systems: readonly TickSystemDefinition<TSystemId>[], anchors: TickAnchors, now: number): ServerTickPlan<TSystemId>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decides which systems a heartbeat should run. A system with no anchor runs immediately.
|
|
3
|
+
* Returned anchors carry only systems present in the pipeline, so removed systems clean up.
|
|
4
|
+
*/
|
|
5
|
+
export function planServerTick(systems, anchors, now) {
|
|
6
|
+
const due = [];
|
|
7
|
+
const nextAnchors = {};
|
|
8
|
+
for (const system of systems) {
|
|
9
|
+
const lastRunAt = anchors[system.id];
|
|
10
|
+
if (lastRunAt !== undefined && now - lastRunAt < system.intervalMs) {
|
|
11
|
+
nextAnchors[system.id] = lastRunAt;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
due.push(system.id);
|
|
15
|
+
nextAnchors[system.id] = now;
|
|
16
|
+
}
|
|
17
|
+
return { due, anchors: nextAnchors };
|
|
18
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface WorldBounds {
|
|
2
|
+
w: number;
|
|
3
|
+
d: number;
|
|
4
|
+
}
|
|
5
|
+
export interface BiomesWorldConfig {
|
|
6
|
+
map: string;
|
|
7
|
+
zones: string;
|
|
8
|
+
bounds?: WorldBounds;
|
|
9
|
+
}
|
|
10
|
+
export interface VoxelWorldConfig {
|
|
11
|
+
seed: string;
|
|
12
|
+
generate?: string;
|
|
13
|
+
streaming?: {
|
|
14
|
+
radius: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface PlotsWorldConfig {
|
|
18
|
+
city?: string;
|
|
19
|
+
interiors?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface TilemapWorldConfig {
|
|
22
|
+
map: string;
|
|
23
|
+
}
|
|
24
|
+
export type WorldFeature = ({
|
|
25
|
+
kind: "biomes";
|
|
26
|
+
} & BiomesWorldConfig) | ({
|
|
27
|
+
kind: "voxel";
|
|
28
|
+
} & VoxelWorldConfig) | ({
|
|
29
|
+
kind: "plots";
|
|
30
|
+
} & PlotsWorldConfig) | ({
|
|
31
|
+
kind: "tilemap";
|
|
32
|
+
} & TilemapWorldConfig) | {
|
|
33
|
+
kind: "flat";
|
|
34
|
+
};
|
|
35
|
+
export declare function biomes(config: BiomesWorldConfig): WorldFeature;
|
|
36
|
+
export declare function voxel(config: VoxelWorldConfig): WorldFeature;
|
|
37
|
+
export declare function plots(config?: PlotsWorldConfig): WorldFeature;
|
|
38
|
+
export declare function tilemap(config: TilemapWorldConfig): WorldFeature;
|
|
39
|
+
export declare function flat(): WorldFeature;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function biomes(config) {
|
|
2
|
+
return { kind: "biomes", ...config };
|
|
3
|
+
}
|
|
4
|
+
export function voxel(config) {
|
|
5
|
+
return { kind: "voxel", ...config };
|
|
6
|
+
}
|
|
7
|
+
export function plots(config = {}) {
|
|
8
|
+
return { kind: "plots", ...config };
|
|
9
|
+
}
|
|
10
|
+
export function tilemap(config) {
|
|
11
|
+
return { kind: "tilemap", ...config };
|
|
12
|
+
}
|
|
13
|
+
export function flat() {
|
|
14
|
+
return { kind: "flat" };
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jgengine/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Genre-agnostic TypeScript game engine SDK: game runtime, state store, entity scene, combat, movement, inventory, economy, quests, multiplayer primitives.",
|
|
5
|
+
"license": "AGPL-3.0-only",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/Noisemaker111/jgengine.git",
|
|
11
|
+
"directory": "packages/core"
|
|
12
|
+
},
|
|
13
|
+
"files": ["dist"],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./*": {
|
|
20
|
+
"types": "./dist/*.d.ts",
|
|
21
|
+
"default": "./dist/*.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.build.json && bun ../../scripts/fix-extensions.ts dist",
|
|
26
|
+
"check-types": "tsc --noEmit -p tsconfig.json",
|
|
27
|
+
"test": "bun test src"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
}
|
|
32
|
+
}
|