Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Commit

Permalink
Merge pull request #73 from topology-foundation/feat/canvas-integration
Browse files Browse the repository at this point in the history
feat: canvas integration (1st part)
  • Loading branch information
d-roak authored Jul 8, 2024
2 parents 2636d48 + ef944b6 commit 74dcc21
Show file tree
Hide file tree
Showing 13 changed files with 1,829 additions and 147 deletions.
1,836 changes: 1,726 additions & 110 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"dev": "vite dev",
"format": "prettier --write .",
"postinstall": "patch-package",
"prepare": "svelte-kit sync",
"preview": "vite preview"
},
Expand All @@ -19,6 +20,7 @@
"@types/lodash-es": "^4.17.12",
"@types/three": "^0.159.0",
"autoprefixer": "^10.4.19",
"patch-package": "^8.0.0",
"postcss": "^8.4.39",
"prettier": "^3.3.2",
"prettier-plugin-svelte": "^3.2.5",
Expand All @@ -27,7 +29,8 @@
"tailwindcss": "^3.4.3",
"tslib": "^2.6.3",
"typescript": "^5.5.2",
"vite": "^5.3.2"
"vite": "^5.3.2",
"vite-plugin-node-polyfills": "^0.22.0"
},
"type": "module",
"dependencies": {
Expand All @@ -37,7 +40,7 @@
"@threlte/extras": "^8.11.4",
"@threlte/rapier": "^2.0.1",
"@threlte/theatre": "^2.1.7",
"@topology-foundation/node": "^0.0.15",
"@topology-foundation/node": "^0.0.20",
"@tweenjs/tween.js": "^23.1.2",
"bits-ui": "^0.21.11",
"clsx": "^2.1.1",
Expand All @@ -46,6 +49,7 @@
"lucide-svelte": "^0.397.0",
"svelte-tweakpane-ui": "^1.3.0",
"tailwind-merge": "^2.3.0",
"three": "^0.159.0"
"three": "^0.159.0",
"util": "^0.12.5"
}
}
12 changes: 11 additions & 1 deletion src/lib/components/PlayersRendering.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { initializePlayerData, startP2PUpdates } from "$lib/store/fakeP2P";
import { Vector3, Euler } from "three";
import Player from "./Player.svelte";
import { nodeId } from "$lib/topology";
let playerModels: Map<PlayerID, any> = new Map();
let playerArray: PlayerData[] = [];
Expand Down Expand Up @@ -59,6 +60,15 @@
onDestroy(() => {
players.clear();
});
function stringToColor(str: string): number {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
let c = (hash & 0x00ffffff).toString(16).toUpperCase();
return parseInt("0x" + "00000".substring(0, 6 - c.length) + c);
}
</script>

{#if playerArray}
Expand All @@ -68,7 +78,7 @@
>
<T.Mesh>
<T.SphereGeometry args={[0.5, 32, 32]} position={[0, 1, 0]} />
<T.MeshBasicMaterial color={0x00ff00} />
<T.MeshBasicMaterial color={stringToColor(nodeId)} />
</T.Mesh>
</T.Group>
{/each}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/ui/sprayWheel.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { sprayWheel, selectedSpray } from "$lib/store/player";
const imageCount = 5;
const imageCount = 7;
let spray: number = 0;
function getImageSrc(index: number): string {
Expand Down
5 changes: 4 additions & 1 deletion src/lib/store/playersData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ export class PlayerData implements Player {
}

updateRotation(rotationX: number, rotationY: number, rotationZ: number) {
this.rotation.set(rotationX, rotationY, rotationZ);
// this.rotation.set(rotationX, rotationY, rotationZ);
this.rotation.x = rotationX;
this.rotation.y = rotationY;
this.rotation.z = rotationZ;
}

updateState(state: "idle" | "running" | "walking" | "jumping") {
Expand Down
1 change: 0 additions & 1 deletion src/lib/store/playersManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { Player, PlayerID } from "./playersData";

export function addOrUpdatePlayer(input: Player): void {
const player = players.get(input.id);
console.log("addOrUpdatePlayer", input, player);
if (player) {
player.updatePosition(input.position.x, input.position.y, input.position.z);
player.updateRotation(input.rotation.x, input.rotation.y, input.rotation.z);
Expand Down
16 changes: 14 additions & 2 deletions src/lib/topology/Update.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
<script lang="ts">
import { onMount } from "svelte";
import { playerPosition } from "$lib/store/player";
import {
playerPosition,
sprayStore,
type SprayData,
} from "$lib/store/player";
import type { Player } from "$lib/store/playersData";
import { Vector3, Euler } from "three";
import { sendPresence, nodeId } from "$lib/topology";
import { addSpray, sendPresence, nodeId } from "$lib/topology";
let previousPosition: Player;
const movementThreshold = 0.01;
Expand All @@ -29,8 +33,16 @@
previousPosition = position;
});
const unsubscribeCanvas = sprayStore.subscribe((sprays: SprayData[]) => {
sprays.forEach((spray) => {
addSpray(spray.timestamp, [spray.offset.x, spray.offset.y], spray.id);
});
});
return () => {
unsubscribe();
unsubscribeCanvas();
};
});
Expand Down
21 changes: 14 additions & 7 deletions src/lib/topology/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { type ICanvas } from "./objects/canvas";
import { OBJECT_ID, PRESENCE_GROUP } from ".";
import { type Player } from "$lib/store/playersData";
import { addOrUpdatePlayer } from "$lib/store/playersManager";
import { addSprayData, type SprayData } from "$lib/store/player";

export function handlePresenceMessages(e: any) {
if (e.detail.msg.topic !== PRESENCE_GROUP) return;
Expand Down Expand Up @@ -34,15 +35,21 @@ function handleObjectUpdate(canvas: ICanvas, fn: string) {
case "addSpray": {
const args = fn.replace("addSpray(", "").replace(")", "").split(",");
let timestamp = parseInt(args[0], 10);
let offset_p = args[1]
.replace("[", "")
.replace("]", "")
.split(",")
.map((s) => parseInt(s, 10));
const offset: [number, number] = [offset_p[0], offset_p[1]];
let sprayType = parseInt(args[2], 10);
let offset_x = parseInt(args[1].replace("[", ""), 10);
let offset_y = parseInt(args[2].replace("]", ""), 10);
const offset: [number, number] = [offset_x, offset_y];
let sprayType = parseInt(args[3], 10);
try {
canvas.addSpray(timestamp, offset, sprayType);
const sprayData: SprayData = {
id: sprayType,
offset: {
x: offset_x,
y: offset_y,
},
timestamp,
};
addSprayData(sprayData);
} catch (e) {
console.error(e);
}
Expand Down
59 changes: 39 additions & 20 deletions src/lib/topology/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { TopologyNode } from "@topology-foundation/node";
import { Vector3, Euler } from "three";
import { fromString as uint8ArrayFromString } from "uint8arrays/from-string";
import { Canvas, type ICanvas } from "./objects/canvas";
import { handleCanvasMessages, handlePresenceMessages } from "./handlers";
import { type Player } from "../store/playersData";
import { addSprayData, type SprayData } from "$lib/store/player";

// exception just for the EthCC demo, the format is not this at all
export const OBJECT_ID = "topology::counter_splash";
Expand All @@ -12,32 +12,48 @@ export const WIDTH = 4000;
export const HEIGHT = 3000;

let node: TopologyNode;
let canvas: Canvas;
export let nodeId: string;

export async function topologyInit() {
node = new TopologyNode();
await node.start();
nodeId = node.getPeerId();

/*
await node.subscribeObject(OBJECT_ID);
let canvas = new Canvas(node.getPeerId(), WIDTH, HEIGHT);
// TODO await for peer connection
canvas = new Canvas(node.getPeerId(), WIDTH, HEIGHT);
canvas.id = OBJECT_ID;
node.createObject(canvas);
node.addCustomGroupMessageHandler((e) => handleCanvasMessages(canvas, e));
*/

node.addCustomGroup(PRESENCE_GROUP);
node.addCustomGroupMessageHandler((e) => handlePresenceMessages(e));

// TODO check best way to handle this
// and when to do full/partial merges (+ policy)
/*
let extCanvas = getObject(OBJECT_ID);
while (extCanvas === null) {
extCanvas = getObject(OBJECT_ID);
while (true) {
try {
await new Promise((resolve) => setTimeout(resolve, 15000));
node.syncObject(OBJECT_ID);
let object: ICanvas | null = getObject(OBJECT_ID);
if (!object) continue;
canvas = object;
// TODO fix this, might be adding on top of existing sprays
for (let spray of canvas.getSprays().set()) {
const tokens = spray.split(",");
const sprayData: SprayData = {
id: parseInt(tokens[3].replace("]", ""), 10),
offset: {
x: parseInt(tokens[1].replace("[", ""), 10),
y: parseInt(tokens[2].replace("]", ""), 10),
},
timestamp: parseInt(tokens[0].replace("[", ""), 10),
};
addSprayData(sprayData);
}
} catch (e) {
console.error(e);
break;
}
}
canvas.merge(extCanvas);
*/
}

export function getObject(id: string): ICanvas | null {
Expand All @@ -47,15 +63,18 @@ export function getObject(id: string): ICanvas | null {
}

export function addSpray(
canvas: ICanvas,
timestamp: number,
offset: [number, number],
sprayType: number,
) {
canvas.addSpray(new Date().getTime(), offset, sprayType);
node.updateObject(
canvas,
`addSpray(${new Date().getTime()},[${offset}],[${sprayType}])`,
);
if (
canvas
.getSprays()
.lookup(`[${timestamp},[${offset[0]},${offset[1]}],${sprayType}]`)
)
return;
canvas.addSpray(timestamp, offset, sprayType);
node.updateObject(canvas, `addSpray(${timestamp},[${offset}],${sprayType})`);
}

export function sendPresence(player: Player) {
Expand Down
11 changes: 11 additions & 0 deletions src/lib/topology/objects/canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ export class Canvas extends TopologyObject implements ICanvas {
}

merge(peerCanvas: Canvas): void {
// TODO ugly, fix this
// protobufs should solve this
peerCanvas = Object.assign(new Canvas("", 0, 0), peerCanvas);
peerCanvas.sprays = Object.assign(
new GSet<String>(new Set()),
peerCanvas.sprays,
);
peerCanvas.sprays._set = Object.assign(
new Set<String>(),
peerCanvas.sprays._set,
);
this.sprays.merge(peerCanvas.getSprays());
}
}
Binary file added static/sprays/spray6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/sprays/spray7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
import { nodePolyfills } from "vite-plugin-node-polyfills";

export default defineConfig({
plugins: [sveltekit()],
plugins: [sveltekit(), nodePolyfills()],
ssr: {
noExternal: ["three"],
},
Expand Down

0 comments on commit 74dcc21

Please sign in to comment.