chore: separate client and rendering components to separate package

This commit is contained in:
Filip Pajic 2024-06-19 12:13:20 +02:00
parent c51ce0a60b
commit 59c868f568
No known key found for this signature in database
29 changed files with 204 additions and 77 deletions

View File

@ -0,0 +1,20 @@
{
"name": "@acid-info/webcave-client",
"version": "0.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "rimraf dist && rollup --config"
},
"dependencies": {
"@types/react": "^18.2.66",
"gl-matrix": "3.4.3",
"rollup": "^2.60.2",
"rollup-plugin-typescript2": "^0.31.1",
"tslib": "^2.3.1",
"typescript": "^5.4.5"
},
"devDependencies": {
"rimraf": "^3.0.2"
}
}

View File

@ -0,0 +1,16 @@
import typescript from 'rollup-plugin-typescript2';
export default {
input: ["src/index.ts"],
output: [
{
dir: "dist",
entryFileNames: "[name].js",
format: "cjs",
exports: "named",
}
],
plugins: [
typescript(),
]
};

View File

@ -0,0 +1 @@
export type * from "./index"

View File

@ -0,0 +1,9 @@
import Renderer from '../../webcave-client/src/renderer'
import Player from '../../webcave-client/src/player'
export {
Renderer,
Player
}
export { SELECTOR_WIDTH_PX } from "./shared/ui"

View File

@ -1,17 +1,30 @@
import World from '../world'
import Vector from '../shared/vector'
import { EMaterial, Material } from '../types/material'
import { MATERIALS } from '../material'
import { DynamicObject } from '../types/util'
import { EChatActions, ACTION_TO_KEYBOARD_KEY_MAP, EKeyboardActions, EActions } from './controls'
import { EMouseEvent } from '../types/controls'
import { CanvasPosition } from './webgl'
import Renderer from './renderer'
import { Collision, DirectedLine, Rectangle, Square, WebGLObject } from '../types/gl'
import { lineRectCollide, rectRectCollide } from '../shared/helpers'
import { SELECTOR_WIDTH_PX } from './ui'
import {
World,
Vector,
EMaterial,
Material,
MATERIALS,
EMouseEvent,
lineRectCollide,
rectRectCollide,
IPlayer,
Collision,
DirectedLine,
Rectangle,
Square,
} from "@acid-info/webcave-core/src"
class Player {
import { EChatActions, ACTION_TO_KEYBOARD_KEY_MAP, EKeyboardActions, EActions } from './shared/controls'
import { CanvasPosition } from './shared/webgl'
import Renderer from './renderer'
import { SELECTOR_WIDTH_PX } from './shared/ui'
import { DynamicObject } from './types/util'
import {
WebGLObject,
} from "./types/gl"
class Player implements IPlayer {
public world: World;
public canvas: HTMLCanvasElement;
@ -81,7 +94,7 @@ class Player {
selector.onclick = () => {
selector.style.opacity = "1.0";
this.prevSelector.style.opacity = null;
this.prevSelector.style.opacity = "";
this.prevSelector = selector;
this.buildMaterial = MATERIALS[mat];

View File

@ -1,14 +1,23 @@
import { WebGl, WebGLBufferWithVertices, WebGLObject, WebGLTextureWithImage } from '../types/gl'
import {
World,
Vector,
MATERIALS,
EMaterial,
Block,
Chunk,
IRenderer,
} from '@acid-info/webcave-core/src'
import { mat4 } from "gl-matrix"
import World from '../world'
import Vector from '../shared/vector'
import { MATERIALS } from '../material'
import { EMaterial } from '../types/material'
import Block from '../block'
import { WEB_GL_SOURCE } from './webgl'
import { Chunk } from '../types/chunk'
import { WEB_GL_SOURCE } from './shared/webgl'
class Renderer {
import {
WebGl,
WebGLBufferWithVertices,
WebGLObject,
WebGLTextureWithImage
} from "./types/gl"
class Renderer implements IRenderer {
public readonly canvas: HTMLCanvasElement;
public readonly gl: WebGl;
public program: WebGLProgram;
@ -146,7 +155,7 @@ class Renderer {
this.gl.bindTexture( this.gl.TEXTURE_2D, this.texTerrain );
if ( chunks != null ) {
for ( var i = 0; i < chunks.length; i++ ) {
for ( let i = 0; i < chunks.length; i++ ) {
if ( chunks[i].buffer != null )
this.drawBuffer( chunks[i].buffer );
}

View File

@ -1,4 +1,4 @@
import { DynamicObject } from '../types/util'
import { AllKeysRequired, DynamicObject } from '../types/util'
export enum EChatActions {
OPEN_CHAT = 'OPEN_CHAT'
@ -14,7 +14,7 @@ export enum EKeyboardActions {
export type EActions = EChatActions | EKeyboardActions;
export const ACTION_TO_KEYBOARD_KEY_MAP: DynamicObject<string, EActions> = {
export const ACTION_TO_KEYBOARD_KEY_MAP: DynamicObject<string, EActions, AllKeysRequired> = {
[EChatActions.OPEN_CHAT]: "t",
[EKeyboardActions.MOVE_FORWARD]: "w",
[EKeyboardActions.MOVE_BACKWARD]: "s",

View File

@ -0,0 +1,17 @@
export type WebGl = WebGLRenderingContext & {
viewportWidth?: number;
viewportHeight?: number;
}
export type WebGLTextureWithImage = WebGLTexture & {
image?: HTMLImageElement;
}
export type WebGLBufferWithVertices = WebGLBuffer & {
vertices?: number;
}
export type WebGLObject = {
texture: WebGLTexture,
model: WebGLBufferWithVertices
}

View File

@ -0,0 +1,9 @@
export type DynamicObject<
Value = any,
Key extends string | number = string,
AllKeysRequired = false,
> = AllKeysRequired extends true
? { [K in Key]: Value }
: { [K in Key]?: Value }
export type AllKeysRequired = true

View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"outDir": "./dist",
"declaration": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist/out-tsc",
"lib": ["DOM", "DOM.Iterable"],
"types": ["node"]
},
"exclude": ["**/*.spec.ts", "**/*.spec.tsx", "node_modules", "./dist/**/*"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

View File

@ -12,7 +12,7 @@
"rollup": "^2.60.2",
"rollup-plugin-typescript2": "^0.31.1",
"tslib": "^2.3.1",
"typescript": "^4.5.2"
"typescript": "^5.4.5"
},
"devDependencies": {
"rimraf": "^3.0.2"

View File

@ -9,7 +9,6 @@ class Block {
return MATERIALS[id]
}
// @TODO typings for lightmap
public static pushVertices(vertices: number[], world: World, lightmap: any, x: number, y: number, z: number ) {
let blocks = world.blocks;
let blockLit = z >= lightmap[x][y];

View File

@ -1,11 +1,19 @@
import World from "./world"
import Renderer from './render/renderer'
import Player from './render/player'
import Physics from './physics'
export {
World,
Renderer,
Player,
Physics
}
export { default as Block } from "./block"
export { MATERIALS } from "./material"
export * from "./types/game"
export * from "./types/controls"
export * from "./types/material"
export * from "./types/chunk"
export * from "./types/gl"
export * from "./shared/helpers"
export { default as Vector } from "./shared/vector"

View File

@ -6,7 +6,10 @@ export const MATERIALS: DynamicObject<Material, EMaterial, AllKeysRequired> = {
[EMaterial.AIR]: {
id: EMaterial.AIR,
spawnable: false,
transparent: true
transparent: true,
texture: () => {
return [0, 0, 0, 0]
}
},
[EMaterial.BEDROCK]: {
id: EMaterial.BEDROCK,

View File

@ -1,15 +1,18 @@
import { Line, Rectangle, Square } from '../types/gl'
// lineRectCollide( line, rect )
//
// Checks if an axis-aligned line and a bounding box overlap.
// line = { y, x1, x2 } or line = { x, y1, y2 }
// rect = { x, y, size }
import { Line, Rectangle, Square } from '../types/gl'
export function lineRectCollide(line: Line, rect: Square) {
if (line.y)
if (line.y) {
return rect.y > line.y - rect.size/2 && rect.y < line.y + rect.size/2 && rect.x > line.x1 - rect.size/2 && rect.x < line.x2 + rect.size/2;
else
} else if (line.x) {
return rect.x > line.x - rect.size/2 && rect.x < line.x + rect.size/2 && rect.y > line.y1 - rect.size/2 && rect.y < line.y2 + rect.size/2;
}
return false;
}
// rectRectCollide( r1, r2 )

View File

@ -2,7 +2,7 @@ export type Chunk = {
start: ChunkSize,
end: ChunkSize,
dirty: boolean,
buffer?: WebGLBuffer
buffer?: any
}
export type ChunkSize = [

View File

@ -0,0 +1,15 @@
export interface IRenderer {
onBlockChanged: (x: number, y: number, z: number) => void;
}
export interface IPlayer {
moving: boolean,
aniframe: number,
pitch: number,
x: number,
y: number,
z: number,
yaw: number,
nick: string,
nametag: any
}

View File

@ -1,21 +1,3 @@
export type WebGl = WebGLRenderingContext & {
viewportWidth?: number;
viewportHeight?: number;
}
export type WebGLTextureWithImage = WebGLTexture & {
image?: HTMLImageElement;
}
export type WebGLBufferWithVertices = WebGLBuffer & {
vertices?: number;
}
export type WebGLObject = {
texture: WebGLTexture,
model: WebGLBufferWithVertices
}
export type Square = {
x: number,
y: number,

View File

@ -18,7 +18,6 @@ import { EDirection } from './controls'
*/
type TexturePositionTuple = [x1: number, y1: number, x2: number, y2: number];
// @TODO typings for lightmap
type GetTexture = (params: {
world: World,
lightmap: any,
@ -58,5 +57,5 @@ export type Material = {
selflit?: boolean;
gravity?: boolean;
fluid?: boolean;
texture?: GetTexture
texture: GetTexture
}

View File

@ -2,8 +2,10 @@ import Vector from './shared/vector'
import { MATERIALS } from './material'
import { EMaterial, Material } from './types/material'
import Block from './block'
import Renderer from './render/renderer'
import Player from './render/player'
import {
IRenderer as Renderer,
IPlayer as Player
} from "./types/game"
/*
* World container
@ -109,7 +111,7 @@ class World {
* Returns a string representation of this world.
* */
public toNetworkString() {
let blockArray = [];
let blockArray: string[] = [];
for ( let x = 0; x < this.sx; x++ )
for ( let y = 0; y < this.sy; y++ )

View File

@ -1,9 +1,9 @@
{
"extends": "./tsconfig.json",
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist/out-tsc",
"types": ["node"]
},
"exclude": ["**/*.spec.ts", "**/*.spec.tsx", "node_modules"],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx", "node_modules", "./dist/**/*"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

View File

@ -19,10 +19,11 @@
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"@acid-info/webcave-core": "*",
"@acid-info/webcave-client": "*",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"typescript": "^5.2.2",
"typescript": "^5.4.5",
"vite": "^5.2.0",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0"

View File

@ -1,12 +1,11 @@
import React from 'react'
import { DEFAULT_WORLD_STRING } from './WebCave.defaultWorld.ts'
import { WebCaveGameState } from './WebCave.types.ts'
import { Physics, Player, Renderer, World } from '@acid-info/webcave-core/src'
import { Physics, World } from '@acid-info/webcave-core/src'
import { Player, Renderer, SELECTOR_WIDTH_PX } from "@acid-info/webcave-client/src"
import styled from '@emotion/styled'
import { MouseEventHandler, useEffect, useRef, useState } from 'react'
const SELECTOR_WIDTH_PX = 40;
export default function WebCave() {
const [gameState, setGameState] = useState<WebCaveGameState>()
const webCaveRenderSurface = useRef<HTMLCanvasElement>(null);

View File

@ -1,9 +1,12 @@
import {
Physics,
World,
World
} from '@acid-info/webcave-core/src'
import {
Renderer,
Player
} from '@acid-info/webcave-core/src'
} from "@acid-info/webcave-client/src"
export type WebCaveGameState = {
world: World

View File

@ -2,7 +2,7 @@
"compilerOptions": {
/* Emit */
"target": "ES2020",
"lib": ["ESNext"],
"lib": ["ES2020"],
"declaration": true,
// These two options will be selectively overridden in each project.
// Utility libraries will have source maps on, but plugins will not.
@ -26,7 +26,7 @@
"noImplicitThis": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"strictNullChecks": false,
"strictPropertyInitialization": false,
"useUnknownInCatchVariables": true,
/* Handled by ESLint */

View File

@ -5426,16 +5426,11 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
"typescript@>=3 < 6", typescript@^5.2.2:
"typescript@>=3 < 6", typescript@^5.4.5:
version "5.4.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
typescript@^4.5.2:
version "4.9.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
uglify-js@^3.1.4:
version "3.17.4"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c"