todo!(game-logic): migrate game files to the engine
This commit is contained in:
parent
bbb1376f95
commit
ce46a43061
62
todo/Game.ts
Normal file
62
todo/Game.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import { Stage } from '@pixi/layers'
|
||||
import type { Application as GameApplication, ICanvas } from 'pixi.js'
|
||||
import { Application, BaseTexture, Container, SCALE_MODES, settings } from 'pixi.js'
|
||||
|
||||
import { GameLogger } from './GameLogger'
|
||||
import type { GameConfigType } from './config'
|
||||
import { GameConfig } from './config'
|
||||
|
||||
export interface IGame extends GameConfigType {
|
||||
container: HTMLCanvasElement
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export class Game {
|
||||
private static INSTANCE: Game
|
||||
private static readonly logger = new GameLogger('🕹️ Habbo Game')
|
||||
|
||||
private readonly _canvas: ICanvas
|
||||
private readonly _application: GameApplication
|
||||
|
||||
// private readonly _manager = RoomManager
|
||||
|
||||
constructor(renderer: IGame) {
|
||||
/** Change the PixiJS settings and default settings */
|
||||
settings.RESOLUTION = 1
|
||||
Container.defaultSortableChildren = true
|
||||
BaseTexture.defaultOptions.scaleMode = SCALE_MODES.NEAREST
|
||||
|
||||
/** Create the PixiJS application */
|
||||
this._application = new Application({
|
||||
width: renderer.width,
|
||||
height: renderer.height,
|
||||
resolution: 1,
|
||||
antialias: false
|
||||
})
|
||||
|
||||
/** Support for PIXI.js dev-tool */
|
||||
// @ts-expect-error
|
||||
if (import.meta.env.DEV) globalThis.__PIXI_APP__ = this._application
|
||||
|
||||
/** Initiate configuration */
|
||||
this._application.stage = new Stage()
|
||||
// RoomManager.init()
|
||||
|
||||
/** Append it to the canvas */
|
||||
this._canvas = this._application.view
|
||||
renderer.container.append(this._application.view as unknown as Node)
|
||||
}
|
||||
|
||||
public static launch(config: GameConfigType): void {
|
||||
if (Object.keys(GameConfig.current).length === 0) GameConfig.init(config)
|
||||
if (this.INSTANCE != null) return this.logger.error('An instance of the game already exists.')
|
||||
|
||||
this.INSTANCE = new this({
|
||||
container: document.getElementById('root') as HTMLCanvasElement,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
config
|
||||
})
|
||||
}
|
||||
}
|
74
todo/GameConfig.ts
Normal file
74
todo/GameConfig.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
import type { ZodError, z } from 'zod'
|
||||
import { fromZodError } from 'zod-validation-error'
|
||||
|
||||
import { GameConfigSchema } from './schemas'
|
||||
import { GameLogger } from '../GameLogger'
|
||||
|
||||
type KeyOf<T> = T extends object
|
||||
? {
|
||||
[K in keyof T]-?: K | `${K & string}.${KeyOf<T[K]> & string}`
|
||||
}[keyof T]
|
||||
: never
|
||||
|
||||
type ValueOf<T, K extends KeyOf<T>> = K extends `${infer U}.${infer R}`
|
||||
? U extends keyof T
|
||||
? ValueOf<T[U], Extract<R, KeyOf<T[U]>>>
|
||||
: never
|
||||
: K extends keyof T
|
||||
? T[K]
|
||||
: never
|
||||
|
||||
export type GameCoreConfig = z.infer<typeof GameConfigSchema>
|
||||
export type GameConfigType = Record<string, any>
|
||||
|
||||
export class GameConfig {
|
||||
private static _config = {} as GameCoreConfig
|
||||
private static readonly _logger = new GameLogger('🛠️ GameConfig', false)
|
||||
|
||||
private static _isValid = false
|
||||
|
||||
public static init(config: GameConfigType): void {
|
||||
try {
|
||||
GameConfigSchema.parse(config)
|
||||
|
||||
this._config = config as GameCoreConfig
|
||||
this._isValid = true
|
||||
} catch (error) {
|
||||
const validationError = fromZodError(error as ZodError, {
|
||||
issueSeparator: '\n',
|
||||
prefixSeparator: '',
|
||||
prefix: ''
|
||||
})
|
||||
|
||||
const lines = validationError.message.split('\n')
|
||||
|
||||
const errors = lines
|
||||
.map((error, index) => {
|
||||
const shouldSkipLine = index === 0 && lines.length > 1
|
||||
return (error = `${shouldSkipLine ? '\n\n' : ''}• ${error}`)
|
||||
})
|
||||
.join('\n')
|
||||
|
||||
this._isValid = false
|
||||
this._logger.error(errors)
|
||||
}
|
||||
}
|
||||
|
||||
public static getValue<K extends KeyOf<GameCoreConfig>>(key: K): ValueOf<GameCoreConfig, K> {
|
||||
if (Object.keys(GameConfig.current).length === 0) throw new Error('Cannot log this out')
|
||||
|
||||
const keys = key.split('.')
|
||||
const value = keys.reduce((obj: any, key) => obj[key], this._config)
|
||||
|
||||
// refactor!(): obj value changes but its type doesn't | temporary any type for now
|
||||
return value
|
||||
}
|
||||
|
||||
public static get current(): GameCoreConfig {
|
||||
return this._config
|
||||
}
|
||||
|
||||
public static get valid(): boolean {
|
||||
return this._isValid
|
||||
}
|
||||
}
|
66
todo/GameLogger.ts
Normal file
66
todo/GameLogger.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import chalk from 'chalk'
|
||||
|
||||
import { GameConfig } from './config/GameConfig'
|
||||
|
||||
type LoggerTypes = 'DEBUG' | 'WARNING' | 'ERROR' | 'EVENTS' | 'PACKETS'
|
||||
|
||||
const GAME_VERSION = '0.0.0'
|
||||
|
||||
export class GameLogger {
|
||||
private readonly _SUB_PREFIX!: string
|
||||
|
||||
private readonly _PREFIX = (color: { bg: `#${string}`; text: `#${string}` }, type: LoggerTypes): string =>
|
||||
chalk.bgHex('#3742fa').white.bold(` ${this._SUB_PREFIX} `) + chalk.bgHex(color.bg).hex(color.text).bold(` ${type} `)
|
||||
|
||||
private LOG_DEBUG = true
|
||||
private LOG_WARN = true
|
||||
private LOG_ERROR = true
|
||||
private LOG_EVENTS = true
|
||||
private LOG_PACKETS = true
|
||||
|
||||
constructor(subPrefix: string, setupConfig: boolean = true) {
|
||||
this._SUB_PREFIX = subPrefix
|
||||
|
||||
if (setupConfig) this.initConfig()
|
||||
}
|
||||
|
||||
private initConfig(): void {
|
||||
this.LOG_DEBUG = !GameConfig.getValue('system.logs.debug')
|
||||
this.LOG_WARN = !GameConfig.getValue('system.logs.warn')
|
||||
this.LOG_ERROR = !GameConfig.getValue('system.logs.error')
|
||||
this.LOG_EVENTS = !GameConfig.getValue('system.logs.events')
|
||||
this.LOG_PACKETS = !GameConfig.getValue('system.logs.packets')
|
||||
}
|
||||
|
||||
public log(...messages: unknown[]): void {
|
||||
if (!this.LOG_DEBUG) return
|
||||
return console.log(this._PREFIX({ bg: '#353b48', text: '#FFF' }, 'DEBUG'), ...messages)
|
||||
}
|
||||
|
||||
public warn(...messages: unknown[]): void {
|
||||
if (!this.LOG_WARN) return
|
||||
return console.warn(this._PREFIX({ bg: '#f39c12', text: '#000' }, 'WARNING'), ...messages)
|
||||
}
|
||||
|
||||
public error(...messages: unknown[]): void {
|
||||
if (!this.LOG_ERROR) return
|
||||
return console.error(this._PREFIX({ bg: '#c0392b', text: '#FFF' }, 'ERROR'), ...messages)
|
||||
}
|
||||
|
||||
public events(...messages: unknown[]): void {
|
||||
if (!this.LOG_EVENTS) return
|
||||
return console.log(this._PREFIX({ bg: '#27ae60', text: '#FFF' }, 'EVENTS'), ...messages)
|
||||
}
|
||||
|
||||
public packets(...messages: unknown[]): void {
|
||||
if (!this.LOG_PACKETS) return
|
||||
return console.log(this._PREFIX({ bg: '#e17055', text: '#FFF' }, 'PACKETS'), ...messages)
|
||||
}
|
||||
|
||||
public welcome(): void {
|
||||
return console.log(
|
||||
`%c Game Version | 🏷️ ${GAME_VERSION}`,
|
||||
'padding: 0.6rem 1rem 0.5rem 0.6rem; font-size: 1.1em; font-weight: bold; font-family: Courier New; text-transform: uppercase; color: white; border-radius: 4px; background-image: linear-gradient(-225deg, #AC32E4 0%, #7918F2 48%, #4801FF 100%)'
|
||||
)
|
||||
}
|
||||
}
|
15
todo/GameManager.ts
Normal file
15
todo/GameManager.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import type { RoomManager } from './RoomManager'
|
||||
|
||||
export interface IGameManager {
|
||||
init: () => void
|
||||
}
|
||||
|
||||
export class GameManager implements IGameManager {
|
||||
private readonly _soundManager
|
||||
private readonly _cameraManager
|
||||
private readonly _roomManager: RoomManager
|
||||
|
||||
init(): void {
|
||||
console.log('feur')
|
||||
}
|
||||
}
|
20
todo/SocketConnection.ts
Normal file
20
todo/SocketConnection.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import type { Socket } from 'socket.io-client'
|
||||
import io from 'socket.io-client'
|
||||
|
||||
import { GameLogger } from './GameLogger'
|
||||
import { GameConfig } from './config'
|
||||
|
||||
export class SocketConnection {
|
||||
private static _connection: Socket
|
||||
|
||||
private static readonly _logger = new GameLogger('📶 SocketConnection')
|
||||
|
||||
public static createConnection(): void {
|
||||
if (this._connection == null) this._connection = io(GameConfig.getValue('url.socket'))
|
||||
else return this._logger.error('Cannot establish connection, a connection is already up and going!')
|
||||
|
||||
this._connection.on('message', (message) => {
|
||||
console.log(message)
|
||||
})
|
||||
}
|
||||
}
|
7
todo/avatar/Avatar.ts
Normal file
7
todo/avatar/Avatar.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export class Avatar {
|
||||
private static readonly DEFAULT_FIGURE = 'hd-99999-99999'
|
||||
|
||||
private readonly _placeholder: this
|
||||
|
||||
// create a figure
|
||||
}
|
827
todo/avatar/HabboAvatarAnimations.ts
Normal file
827
todo/avatar/HabboAvatarAnimations.ts
Normal file
|
@ -0,0 +1,827 @@
|
|||
export const HabboAvatarAnimations = {
|
||||
animations: [
|
||||
{
|
||||
id: 'Move',
|
||||
parts: [
|
||||
{
|
||||
setType: 'bd',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'bds',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ss',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lg',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'sh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lhs',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ls',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rhs',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rs',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ch',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wlk'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wlk'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'Wave',
|
||||
parts: [
|
||||
{
|
||||
setType: 'lh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wav'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lhs',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wav'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ls',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wav'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wav'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ch',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wav'
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
assetPartDefinition: 'wav'
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
assetPartDefinition: 'wav'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'Talk',
|
||||
parts: [
|
||||
{
|
||||
setType: 'hd',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'spk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'spk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'fc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'spk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'spk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'fa',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'spk'
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'spk'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'Sign',
|
||||
parts: [
|
||||
{
|
||||
setType: 'lh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'sig'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'li',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'sig'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ls',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'Respect',
|
||||
parts: [
|
||||
{
|
||||
setType: 'lh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'respect',
|
||||
repeats: 15
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'respect',
|
||||
repeats: 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ls',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav',
|
||||
repeats: 15
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wav',
|
||||
repeats: 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'lc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'wav',
|
||||
repeats: 15
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'wav',
|
||||
repeats: 15
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'Blow',
|
||||
parts: [
|
||||
{
|
||||
setType: 'rh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'blw',
|
||||
repeats: 10
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
assetPartDefinition: 'blw',
|
||||
repeats: 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rs',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'drk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'drk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ri',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ey',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'std',
|
||||
repeats: 10
|
||||
},
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'eyb',
|
||||
repeats: 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'fc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'std',
|
||||
repeats: 10
|
||||
},
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'blw',
|
||||
repeats: 10
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'Laugh',
|
||||
parts: [
|
||||
{
|
||||
setType: 'rh',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'blw'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rs',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'drk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'rc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'drk'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ri',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'ey',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'std',
|
||||
repeats: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
setType: 'fc',
|
||||
frames: [
|
||||
{
|
||||
number: 0,
|
||||
assetPartDefinition: 'sml'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
offsets: {
|
||||
frames: [
|
||||
{
|
||||
id: 0,
|
||||
directions: [
|
||||
{
|
||||
id: 0,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
directions: [
|
||||
{
|
||||
id: 0,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
bodyParts: [
|
||||
{
|
||||
id: 'head',
|
||||
dx: 0,
|
||||
dy: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
1830
todo/avatar/HabboAvatarGeometry.ts
Normal file
1830
todo/avatar/HabboAvatarGeometry.ts
Normal file
File diff suppressed because it is too large
Load Diff
418
todo/avatar/HabboAvatarPartSets.ts
Normal file
418
todo/avatar/HabboAvatarPartSets.ts
Normal file
|
@ -0,0 +1,418 @@
|
|||
export const HabboAvatarPartSets = {
|
||||
partSets: {
|
||||
partSet: [
|
||||
{
|
||||
setType: 'ri',
|
||||
flippedSetType: 'ri'
|
||||
},
|
||||
{
|
||||
setType: 'ri',
|
||||
flippedSetType: 'ri'
|
||||
},
|
||||
{
|
||||
setType: 'rh',
|
||||
flippedSetType: 'lh'
|
||||
},
|
||||
{
|
||||
setType: 'rhs',
|
||||
flippedSetType: 'lhs'
|
||||
},
|
||||
{
|
||||
setType: 'rs',
|
||||
swim: '0',
|
||||
flippedSetType: 'ls'
|
||||
},
|
||||
{
|
||||
setType: 'rc',
|
||||
flippedSetType: 'lc'
|
||||
},
|
||||
{
|
||||
setType: 'bd'
|
||||
},
|
||||
{
|
||||
setType: 'bds'
|
||||
},
|
||||
{
|
||||
setType: 'ss'
|
||||
},
|
||||
{
|
||||
setType: 'sh'
|
||||
},
|
||||
{
|
||||
setType: 'lg'
|
||||
},
|
||||
{
|
||||
setType: 'ch'
|
||||
},
|
||||
{
|
||||
setType: 'cp'
|
||||
},
|
||||
{
|
||||
setType: 'cc'
|
||||
},
|
||||
{
|
||||
setType: 'hd'
|
||||
},
|
||||
{
|
||||
setType: 'fc'
|
||||
},
|
||||
{
|
||||
setType: 'ey'
|
||||
},
|
||||
{
|
||||
setType: 'hr'
|
||||
},
|
||||
{
|
||||
setType: 'hrb',
|
||||
removeSetType: 'hr'
|
||||
},
|
||||
{
|
||||
setType: 'li',
|
||||
flippedSetType: 'li'
|
||||
},
|
||||
{
|
||||
setType: 'lh',
|
||||
flippedSetType: 'rh'
|
||||
},
|
||||
{
|
||||
setType: 'lhs',
|
||||
flippedSetType: 'rhs'
|
||||
},
|
||||
{
|
||||
setType: 'ls',
|
||||
flippedSetType: 'rs'
|
||||
},
|
||||
{
|
||||
setType: 'lc',
|
||||
flippedSetType: 'rc'
|
||||
},
|
||||
{
|
||||
setType: 'wa'
|
||||
},
|
||||
{
|
||||
setType: 'ea'
|
||||
},
|
||||
{
|
||||
setType: 'ca'
|
||||
},
|
||||
{
|
||||
setType: 'fa'
|
||||
},
|
||||
{
|
||||
setType: 'ha'
|
||||
},
|
||||
{
|
||||
setType: 'he'
|
||||
}
|
||||
],
|
||||
activePartSets: [
|
||||
{
|
||||
id: 'figure',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'rh'
|
||||
},
|
||||
{
|
||||
setType: 'rh'
|
||||
},
|
||||
{
|
||||
setType: 'rhs'
|
||||
},
|
||||
{
|
||||
setType: 'rs'
|
||||
},
|
||||
{
|
||||
setType: 'rc'
|
||||
},
|
||||
{
|
||||
setType: 'bd'
|
||||
},
|
||||
{
|
||||
setType: 'bds'
|
||||
},
|
||||
{
|
||||
setType: 'ss'
|
||||
},
|
||||
{
|
||||
setType: 'sh'
|
||||
},
|
||||
{
|
||||
setType: 'lg'
|
||||
},
|
||||
{
|
||||
setType: 'ch'
|
||||
},
|
||||
{
|
||||
setType: 'cp'
|
||||
},
|
||||
{
|
||||
setType: 'cc'
|
||||
},
|
||||
{
|
||||
setType: 'wa'
|
||||
},
|
||||
{
|
||||
setType: 'hd'
|
||||
},
|
||||
{
|
||||
setType: 'fc'
|
||||
},
|
||||
{
|
||||
setType: 'ey'
|
||||
},
|
||||
{
|
||||
setType: 'hr'
|
||||
},
|
||||
{
|
||||
setType: 'hrb'
|
||||
},
|
||||
{
|
||||
setType: 'lh'
|
||||
},
|
||||
{
|
||||
setType: 'lhs'
|
||||
},
|
||||
{
|
||||
setType: 'ls'
|
||||
},
|
||||
{
|
||||
setType: 'lc'
|
||||
},
|
||||
{
|
||||
setType: 'ea'
|
||||
},
|
||||
{
|
||||
setType: 'ca'
|
||||
},
|
||||
{
|
||||
setType: 'fa'
|
||||
},
|
||||
{
|
||||
setType: 'ha'
|
||||
},
|
||||
{
|
||||
setType: 'he'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'head',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'hd'
|
||||
},
|
||||
{
|
||||
setType: 'fc'
|
||||
},
|
||||
{
|
||||
setType: 'ey'
|
||||
},
|
||||
{
|
||||
setType: 'hr'
|
||||
},
|
||||
{
|
||||
setType: 'hrb'
|
||||
},
|
||||
{
|
||||
setType: 'ea'
|
||||
},
|
||||
{
|
||||
setType: 'fa'
|
||||
},
|
||||
{
|
||||
setType: 'ha'
|
||||
},
|
||||
{
|
||||
setType: 'he'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'speak',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'hd'
|
||||
},
|
||||
{
|
||||
setType: 'hr'
|
||||
},
|
||||
{
|
||||
setType: 'hrb'
|
||||
},
|
||||
{
|
||||
setType: 'fc'
|
||||
},
|
||||
{
|
||||
setType: 'fa'
|
||||
},
|
||||
{
|
||||
setType: 'ha'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'gesture',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'ey'
|
||||
},
|
||||
{
|
||||
setType: 'fc'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'eye',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'ey'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'handRight',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'rh'
|
||||
},
|
||||
{
|
||||
setType: 'rhs'
|
||||
},
|
||||
{
|
||||
setType: 'rs'
|
||||
},
|
||||
{
|
||||
setType: 'rc'
|
||||
},
|
||||
{
|
||||
setType: 'ri'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'handRightAndHead',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'rh'
|
||||
},
|
||||
{
|
||||
setType: 'rhs'
|
||||
},
|
||||
{
|
||||
setType: 'rs'
|
||||
},
|
||||
{
|
||||
setType: 'rc'
|
||||
},
|
||||
{
|
||||
setType: 'ri'
|
||||
},
|
||||
{
|
||||
setType: 'ey'
|
||||
},
|
||||
{
|
||||
setType: 'fc'
|
||||
},
|
||||
{
|
||||
setType: 'hd'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'handLeft',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'lh'
|
||||
},
|
||||
{
|
||||
setType: 'lhs'
|
||||
},
|
||||
{
|
||||
setType: 'ls'
|
||||
},
|
||||
{
|
||||
setType: 'lc'
|
||||
},
|
||||
{
|
||||
setType: 'li'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'walk',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'bd'
|
||||
},
|
||||
{
|
||||
setType: 'bds'
|
||||
},
|
||||
{
|
||||
setType: 'ss'
|
||||
},
|
||||
{
|
||||
setType: 'lg'
|
||||
},
|
||||
{
|
||||
setType: 'lh'
|
||||
},
|
||||
{
|
||||
setType: 'lhs'
|
||||
},
|
||||
{
|
||||
setType: 'rh'
|
||||
},
|
||||
{
|
||||
setType: 'rhs'
|
||||
},
|
||||
{
|
||||
setType: 'ls'
|
||||
},
|
||||
{
|
||||
setType: 'lc'
|
||||
},
|
||||
{
|
||||
setType: 'rs'
|
||||
},
|
||||
{
|
||||
setType: 'rc'
|
||||
},
|
||||
{
|
||||
setType: 'sh'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'sit',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'bd'
|
||||
},
|
||||
{
|
||||
setType: 'bds'
|
||||
},
|
||||
{
|
||||
setType: 'ss'
|
||||
},
|
||||
{
|
||||
setType: 'lg'
|
||||
},
|
||||
{
|
||||
setType: 'sh'
|
||||
},
|
||||
{
|
||||
setType: 'cc'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'itemRight',
|
||||
activeParts: [
|
||||
{
|
||||
setType: 'ri'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
31
todo/package.json
Normal file
31
todo/package.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "game",
|
||||
"version": "0.0.0",
|
||||
"description": "Habbo Game core engine",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build-fast": "tsup src/index.ts --format cjs,esm --dts",
|
||||
"build": "pnpm run build-fast -- --dts-resolve",
|
||||
"test": "vitest run",
|
||||
"prepublishOnly": "pnpm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pixi/layers": "^2.1.0",
|
||||
"@pixi/utils": "^7.2.4",
|
||||
"@pixi/core": "7.2.4",
|
||||
"gsap": "^3.12.2",
|
||||
"pixi.js": "^7.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"config": "workspace:*",
|
||||
"@types/node": "20.4.2",
|
||||
"socket.io-client": "4.7.1",
|
||||
"pako": "2.1.0",
|
||||
"zod": "3.21.4",
|
||||
"chalk": "5.3.0",
|
||||
"zod-validation-error": "1.3.1",
|
||||
"tsup": "7.1.0",
|
||||
"typescript": "5.1.6",
|
||||
"vitest": "0.33.0"
|
||||
}
|
||||
}
|
58
todo/schemas.ts
Normal file
58
todo/schemas.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { z } from 'zod'
|
||||
|
||||
const SystemConfig = z.strictObject({
|
||||
logs: z.strictObject({
|
||||
debug: z.boolean(),
|
||||
warn: z.boolean(),
|
||||
error: z.boolean(),
|
||||
events: z.boolean(),
|
||||
packets: z.boolean()
|
||||
}),
|
||||
|
||||
fps: z
|
||||
.strictObject({
|
||||
max: z.number(),
|
||||
animation: z.number().min(24)
|
||||
})
|
||||
.refine(
|
||||
(ctx) => ctx.animation <= ctx.max,
|
||||
(ctx) => ({ message: `Number must not exceed ${ctx.max} max FPS`, path: ['animation'] })
|
||||
),
|
||||
|
||||
pong: z.strictObject({
|
||||
manually: z.boolean(),
|
||||
interval: z
|
||||
.number()
|
||||
.min(5 * 1000)
|
||||
.max(60 * 1000)
|
||||
})
|
||||
})
|
||||
|
||||
const URLConfig = z.strictObject({
|
||||
socket: z.string().refine((value) => value.startsWith('ws://') && /\b(?:\d{1,3}\.){3}\d{1,3}:\d{1,5}\b/.test(value), {
|
||||
message: 'Invalid socket URL format'
|
||||
}),
|
||||
client: z
|
||||
.string()
|
||||
.refine((value) => /^(ht{2}ps?:\/{2})?((([\da-z-]+\.)+[a-z]{2,})|((?:\d{1,3}\.){3}\d{1,3}))(\/.*)?$/i.test(value), {
|
||||
message: 'Invalid HTTP URL format'
|
||||
})
|
||||
})
|
||||
|
||||
const CommonKeys = {
|
||||
enabled: z.boolean()
|
||||
}
|
||||
|
||||
const GameSchema = z.strictObject({
|
||||
hc: z.strictObject({ ...CommonKeys }),
|
||||
camera: z.strictObject({ ...CommonKeys }),
|
||||
pets: z.array(z.string())
|
||||
})
|
||||
|
||||
const GameConfigSchema = z.strictObject({
|
||||
system: SystemConfig,
|
||||
url: URLConfig,
|
||||
game: GameSchema
|
||||
})
|
||||
|
||||
export { GameConfigSchema }
|
16
todo/tsconfig.json
Normal file
16
todo/tsconfig.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitAny": true,
|
||||
"allowJs": true,
|
||||
"noEmit": true,
|
||||
"outDir": "dist",
|
||||
"resolveJsonModule": true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user