diff --git a/package.json b/package.json index b062e7d..e772f5d 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@typescript-eslint/parser": "^6.21.0", "bun": "^1.1.22", "cc-blitzkrieg": "github:krypciak/cc-blitzkrieg", + "cc-hotreload": "github:krypciak/cc-hotreload", "ccmodmanager": "github:CCDirectLink/CCModManager", "colorts": "^0.1.63", "esbuild": "^0.18.20", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5c9559..e311b66 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: cc-blitzkrieg: specifier: github:krypciak/cc-blitzkrieg version: https://codeload.github.com/krypciak/cc-blitzkrieg/tar.gz/be28d62634ffe5b797046c49846fb821a8d35c6d + cc-hotreload: + specifier: github:krypciak/cc-hotreload + version: https://codeload.github.com/krypciak/cc-hotreload/tar.gz/80118b9d099e24c6b57d52e76be47633babd18f1 ccmodmanager: specifier: github:CCDirectLink/CCModManager version: https://codeload.github.com/CCDirectLink/CCModManager/tar.gz/46a67246711879ecdaf620e670b86afdc2e6d5a2 @@ -424,6 +427,10 @@ packages: resolution: {tarball: https://codeload.github.com/krypciak/cc-blitzkrieg/tar.gz/be28d62634ffe5b797046c49846fb821a8d35c6d} version: 0.5.9 + cc-hotreload@https://codeload.github.com/krypciak/cc-hotreload/tar.gz/80118b9d099e24c6b57d52e76be47633babd18f1: + resolution: {tarball: https://codeload.github.com/krypciak/cc-hotreload/tar.gz/80118b9d099e24c6b57d52e76be47633babd18f1} + version: 0.0.1 + ccmodmanager@https://codeload.github.com/CCDirectLink/CCModManager/tar.gz/46a67246711879ecdaf620e670b86afdc2e6d5a2: resolution: {tarball: https://codeload.github.com/CCDirectLink/CCModManager/tar.gz/46a67246711879ecdaf620e670b86afdc2e6d5a2} version: 0.9.20 @@ -1218,6 +1225,8 @@ snapshots: dependencies: '@types/jszip': 3.4.1 + cc-hotreload@https://codeload.github.com/krypciak/cc-hotreload/tar.gz/80118b9d099e24c6b57d52e76be47633babd18f1: {} + ccmodmanager@https://codeload.github.com/CCDirectLink/CCModManager/tar.gz/46a67246711879ecdaf620e670b86afdc2e6d5a2: {} chalk@4.1.2: diff --git a/src/area/area-json-creator.ts b/src/area/area-json-creator.ts index de59fd0..0523997 100644 --- a/src/area/area-json-creator.ts +++ b/src/area/area-json-creator.ts @@ -1,7 +1,6 @@ import { Id } from '../build-queue/build-queue' -import { RoomArrange } from '../map-arrange/map-arrange' import { AreaInfo, MapConstruct, RoomConsturct } from '../map-construct/map-construct' -import { Rect } from '../util/geometry' +import { Dir, DirU, Rect } from '../util/geometry' import { ObjectEntriesT } from '../util/modify-prototypes' import { allLangs, assert } from '../util/util' import { Vec2 } from '../util/vec2' @@ -43,6 +42,14 @@ declare global { areaRect?: Rect })[] } + interface Connection { + dir: Dir + tx: number + ty: number + size: number + map1: number + map2: number + } } } } @@ -55,7 +62,7 @@ export function createArea( chests: number, floorNames: Record ): sc.AreaLoadable.SDCustom.Data { - const bounds: Rect = Rect.boundsOfArr(maps.flatMap(a => a.rectsAbsolute)) + const bounds: Rect = Rect.boundsOfArr(maps.flatMap(a => a.arrangeCopy.rects)) const divider = 64 const offset = Vec2.divC(Vec2.copy(bounds), divider) const size = Vec2.divC({ x: bounds.width, y: bounds.height }, divider) @@ -70,9 +77,30 @@ export function createArea( for (const [floor, maps] of ObjectEntriesT(mapsByFloor)) { if (floor == defaultFloor) actualDefaultFloor = floors.length + const connections: sc.AreaLoadable.SDCustom.Connection[] = [] + const offsetDas = Vec2.divC(Rect.boundsOfArr(maps.flatMap(map => map.arrangeCopy.rects)), divider) const areaMaps: sc.AreaLoadable.SDCustom.Map[] = maps.map(map => { - const boundsAbsolute: Rect = Rect.boundsOfArr(map.rectsAbsolute) + const boundsAbsolute: Rect = Rect.boundsOfArr(map.arrangeCopy.rects) const offsetRelative: Vec2 = Vec2.divC(Rect.boundsOfArr(map.rects), divider) + + for (const tpr of [...map.arrangeCopy.entranceTprs, ...map.arrangeCopy.restTprs]) { + if (tpr.noDrawConnection) continue + if (tpr.destId < map.id) continue + assert(DirU.isDir(tpr.dir)) + + const pos: Vec2 = Vec2.copy(tpr) + Vec2.divC(pos, divider) + Vec2.sub(pos, offsetDas) + connections.push({ + tx: pos.x, + ty: pos.y, + dir: tpr.dir, + size: 3, + map1: tpr.destId, + map2: map.id, + }) + } + return { path: map.constructed.name.replace('/', '.'), name: allLangs(map.title), @@ -100,7 +128,7 @@ export function createArea( size, maps: areaMaps, - connections: [], + connections, icons: [], landmarks: [], }) diff --git a/src/area/custom-area-container.ts b/src/area/custom-area-container.ts index 431b4f5..8dbefe7 100644 --- a/src/area/custom-area-container.ts +++ b/src/area/custom-area-container.ts @@ -1,5 +1,6 @@ import { Rect, Dir } from '../util/geometry' import { assert } from '../util/util' +import { Vec2 } from '../util/vec2' export {} @@ -10,7 +11,7 @@ interface AreaRendererColorScheme { shadow: ig.SimpleColor } -const addPxSpace: number = 0 +const addPxSpace: number = 4 sc.MapAreaContainer.inject({ findMap(mx: number, my: number, gamepad: boolean, wait?: number): boolean | undefined { if (sc.menu.mapMapFocus) return @@ -19,12 +20,12 @@ sc.MapAreaContainer.inject({ let pos: Vec2 if (gamepad) { - pos = Vec2.create(this.area.hook.pos) + pos = Vec2.copy(this.area.hook.pos) } else { - pos = Vec2.createC( - mx - sc.menu.mapCamera.x - this.area.hook.pos.x + 1, - my - sc.menu.mapCamera.y - this.area.hook.pos.y + 1 - ) + pos = { + x: mx - sc.menu.mapCamera.x - this.area.hook.pos.x + 1, + y: my - sc.menu.mapCamera.y - this.area.hook.pos.y + 1, + } } Vec2.subC(pos, addPxSpace) @@ -162,14 +163,45 @@ type GuiHookMapRoomList = ig.GuiHook & { sc.MapCurrentRoomWrapper.inject({ init(hook: ig.GuiHook) { const floor = (hook as GuiHookMapRoomList).gui.floor - if (!floor.shaduungeonCustom) return this.parent(hook) + if (!floor.shaduungeonCustom) { + this.parent(hook) + this.doStateTransition('HIDDEN') + return + } this.parent({ pos: { x: hook.pos.x + addPxSpace, y: hook.pos.y + addPxSpace }, size: { x: hook.size.x - addPxSpace * 2, y: hook.size.y - addPxSpace * 2 }, } as ig.GuiHook) + this.doStateTransition('HIDDEN') }, }) +function drawConnection(v: Vec2, connection: sc.AreaLoadable.SDCustom.Connection) { + assert(connection.size == 3) + let { x, y } = v + y += 2 + x += 2 + let h = 4 + if (connection.dir == Dir.NORTH) { + inactiveColors.empty.draw(x, y, connection.size, h) + inactiveColors.border.draw(x - 1, y + 1, 1, h - 2) + inactiveColors.border.draw(x + connection.size, y + 1, 1, h - 2) + } else if (connection.dir == Dir.EAST) { + inactiveColors.empty.draw(x, y, connection.size, h) + inactiveColors.border.draw(x, y - 1, connection.size, 1) + inactiveColors.shadow.draw(x, y, connection.size, 2) + inactiveColors.border.draw(x, y + connection.size, connection.size, 1) + } else if (connection.dir == Dir.SOUTH) { + inactiveColors.empty.draw(x, y, connection.size, h + 1) + inactiveColors.border.draw(x - 1, y, 1, h - 1) + inactiveColors.border.draw(x + connection.size, y, 1, h - 1) + } else if (connection.dir == Dir.WEST) { + inactiveColors.empty.draw(x, y, connection.size, h) + inactiveColors.border.draw(x, y - 1, connection.size, 1) + inactiveColors.shadow.draw(x, y, connection.size, 2) + inactiveColors.border.draw(x, y + connection.size, connection.size, 1) + } +} sc.MapRoom.inject({ init(room, _floor, id) { @@ -195,52 +227,22 @@ sc.MapRoom.inject({ assert(map.rects) const c = this.active ? activeColors : inactiveColors - /* - function drawConnection(x: number, y: number, connection: sc.AreaLoadable.ConnectionRoomList) { - const h = 4 - switch (connection.dir) { - case Dir.NORTH: - inactiveColors.empty.draw(x, y, connection.size, h) - inactiveColors.border.draw(x - 1, y + 1, 1, h - 1) - inactiveColors.border.draw(x + connection.size, y + 1, 1, h - 1) - break - case Dir.EAST: - inactiveColors.empty.draw(x, y, connection.size, h) - inactiveColors.border.draw(x, y - 1, connection.size, 1) - inactiveColors.border.draw(x, y + connection.size, connection.size, 1) - break - case Dir.SOUTH: - inactiveColors.empty.draw(x, y, connection.size, h) - inactiveColors.border.draw(x - 1, y, 1, h - 1) - inactiveColors.border.draw(x + connection.size, y, 1, h - 1) - break - case Dir.WEST: - inactiveColors.empty.draw(x, y, connection.size, h) - inactiveColors.border.draw(x, y - 1, connection.size, 1) - inactiveColors.border.draw(x, y + connection.size, connection.size, 1) - break - } - } - */ - this.buffer = ig.imageAtlas.getFragment(this.hook.size.x, this.hook.size.y, () => { /* draw black on south and east edges */ for (const o of map.rects) { - if (!o.drawRect) { - const rect = { - x: o.x * tilesize + addPxSpace, - y: o.y * tilesize + addPxSpace, - width: o.width * tilesize, - height: o.height * tilesize, - x2: 0, - y2: 0, - } - o.drawRect = rect - o.drawEmptyRect = Rect.copy(rect) - rect.x2 = rect.x + rect.width - 1 - rect.y2 = rect.y + rect.height - 1 + const rect = { + x: o.x * tilesize + addPxSpace, + y: o.y * tilesize + addPxSpace, + width: o.width * tilesize, + height: o.height * tilesize, + x2: 0, + y2: 0, } - const rect = o.drawRect + o.drawRect = rect + o.drawEmptyRect = Rect.copy(rect) + rect.x2 = rect.x + rect.width - 1 + rect.y2 = rect.y + rect.height - 1 + if (o.walls[Dir.SOUTH]) { black.draw(rect.x, rect.y2, rect.width, 1) } @@ -269,7 +271,7 @@ sc.MapRoom.inject({ if (o.walls[Dir.SOUTH]) { c.border.draw(rect.x - biNX, rect.y2 - 1, rect.width + biNX + biPX - 1, 1) } else { - eRect.height += tunnelClear + eRect.height += tunnelClear + 1 } if (o.walls[Dir.EAST]) { @@ -288,44 +290,31 @@ sc.MapRoom.inject({ for (const o of map.rects) { if (o.walls[Dir.NORTH]) { const rect = o.drawEmptyRect! - c.shadow.draw(rect.x + 1, rect.y + 1, rect.width - 3, 1) + c.shadow.draw(rect.x + 1, rect.y + 1, rect.width - 3, 2) } } /* fill the rooms */ for (const o of map.rects) { const rect = o.drawEmptyRect! - const shadowOffset = o.walls[Dir.NORTH] ? 1 : 0 + const shadowOffset = o.walls[Dir.NORTH] ? 2 : 0 c.empty.draw(rect.x + 1, rect.y + shadowOffset + 1, rect.width - 3, rect.height - shadowOffset - 3) } - /* - const connections: sc.AreaLoadable.ConnectionRoomList[] = this.floor.connections - let i = connections.length - while (i--) { - const connection = connections[i] - // apperently map connections can have a condition? didnt bother implementing that - if (connection.map1 + 1 == this.room.id || connection.map2 + 1 == this.room.id) { - const rect: bareRect = - // @root/ts-ignore - connection.rect - new ig.SimpleColor('#00ff0055').draw( - (rect.x - this.room.min.x) * tilesize + addPxSpace, - (rect.y - this.room.min.y) * tilesize + addPxSpace, - rect.width * tilesize, - rect.height * tilesize - ) - drawConnection( - (connection.tx - this.room.min.x) * tilesize + addPxSpace, - (connection.ty - this.room.min.y) * tilesize + addPxSpace, - connection, - ) - } - } - */ - // activeColors.empty.draw(0, 0, addPxSpace, addPxSpace) - // activeColors.empty.draw(this.hook.size.x - addPxSpace, 0, addPxSpace, addPxSpace) - // activeColors.empty.draw(this.hook.size.x - addPxSpace, this.hook.size.y - addPxSpace, addPxSpace, addPxSpace) - // activeColors.empty.draw(0, this.hook.size.y - addPxSpace, addPxSpace, addPxSpace) + const connections = this.floor.connections as unknown as sc.AreaLoadable.SDCustom.Connection[] + let i = connections.length + while (i--) { + const connection = connections[i] + // apperently map connections can have a condition? didnt bother implementing that + if (connection.map1 + 1 == this.room.id || connection.map2 + 1 == this.room.id) { + drawConnection( + { + x: (connection.tx - this.room.min.x) * tilesize, + y: (connection.ty - this.room.min.y) * tilesize, + }, + connection + ) + } + } }) this.prerendered = true }, diff --git a/src/dungeon/builder.ts b/src/dungeon/builder.ts index d9e50a3..ba69822 100644 --- a/src/dungeon/builder.ts +++ b/src/dungeon/builder.ts @@ -59,11 +59,11 @@ export class DungeonBuilder { root: { type: 'Simple', size: roomSizeReg, - count: 1, + count: 2, randomizeDirTryOrder, followedBy: branch( - 3, + 1, () => 1, () => 1, () => 2 diff --git a/src/map-arrange/map-arrange.ts b/src/map-arrange/map-arrange.ts index 26214c3..9175daf 100644 --- a/src/map-arrange/map-arrange.ts +++ b/src/map-arrange/map-arrange.ts @@ -7,6 +7,7 @@ export interface TprArrange3d extends Vec2 { dir: Dir3d destId: Id destIndex?: number + noDrawConnection?: boolean } export interface TprArrange extends TprArrange3d { dir: Dir diff --git a/src/map-construct/map-construct.ts b/src/map-construct/map-construct.ts index c6186a3..35bca43 100644 --- a/src/map-construct/map-construct.ts +++ b/src/map-construct/map-construct.ts @@ -9,8 +9,8 @@ import { getEmptyLayers } from './layer' import { MapTheme } from './theme' export interface MapConstruct extends MapArrange { + arrangeCopy: MapArrange constructed: sc.MapModel.Map - rectsAbsolute: Rect[] title: string rects: RoomConsturct[] } @@ -67,9 +67,7 @@ export function baseMapConstruct( areaId: string, theme: MapTheme, extend: Record -): { mic: MapInConstruction; rectsAbsolute: Rect[] } { - const rectsAbsolute = map.rects.map(Rect.copy) - +): MapInConstruction { const boundsEntity = Rect.boundsOfArr(map.rects) for (let dir = 0 as Dir; dir < 4; dir++) { @@ -96,7 +94,7 @@ export function baseMapConstruct( ...getEmptyLayers(mapSize, 3, theme.config), } - return { mic, rectsAbsolute } + return mic } export function getTprName(isEntrance: boolean, index: number): string { diff --git a/src/maps/simple.ts b/src/maps/simple.ts index 7116eb8..f1dddda 100644 --- a/src/maps/simple.ts +++ b/src/maps/simple.ts @@ -7,6 +7,7 @@ import { RoomArrange, doesMapArrangeFit, TprArrange3d, + copyMapArrange, } from '../map-arrange/map-arrange' import { MapPicker, registerMapPickerNodeConfig } from '../map-arrange/map-picker/configurable' import { Dir, DirU, Rect } from '../util/geometry' @@ -143,7 +144,8 @@ export const simpleMapConstructor: MapConstructFunc = ( _mapsConstructed ) => { const theme = MapTheme.default - const { mic, rectsAbsolute } = baseMapConstruct(map, pathResolver(map.id), areaInfo.id, theme, [8, 1, 1, 1]) + const arrangeCopy = copyMapArrange(map) + const mic = baseMapConstruct(map, pathResolver(map.id), areaInfo.id, theme, [8, 1, 1, 1]) function pushTprEntity(tpr: TprArrange3d, isEntrance: boolean, index: number) { const name = getTprName(isEntrance, index) @@ -192,7 +194,7 @@ export const simpleMapConstructor: MapConstructFunc = ( ...map, rects, constructed, - rectsAbsolute, + arrangeCopy, title: `map ${constructed.name}`, } } diff --git a/src/plugin.ts b/src/plugin.ts index 40249c6..f0b9c04 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -6,6 +6,8 @@ import { RuntimeResources } from './util/runtime-assets' import { injectGameStarting } from './util/game-start' import * as _ from 'ultimate-crosscode-typedefs' import { DungeonPaths } from './dungeon/paths' +import type * as __ from 'cc-hotreload/src/plugin' +import { registeredMethods } from 'cc-hotreload/src/decorators' export default class DngGen { static dir: string @@ -25,6 +27,8 @@ export default class DngGen { injectGameStarting() import('./area/custom-area-container') DungeonPaths.registerAutoLoadDungeon() + + hotreload.listen(`${DngGen.dir}/plugin.js`, registeredMethods) } async poststart() { diff --git a/src/util/game-start.ts b/src/util/game-start.ts index 36d9efb..7cdef2f 100644 --- a/src/util/game-start.ts +++ b/src/util/game-start.ts @@ -14,10 +14,10 @@ export async function startDnggenGame(titleGuiInstance?: sc.TitleScreenButtonGui ig.game.setPaused(false) const builder = new DungeonBuilder() - builder.build('helo').then(() => { + builder.build('heloo').then(() => { setTimeout(() => { godmode() - }, 2000) + }, 1000) }) } diff --git a/src/util/geometry.ts b/src/util/geometry.ts index 37b9043..f952276 100644 --- a/src/util/geometry.ts +++ b/src/util/geometry.ts @@ -45,9 +45,12 @@ export namespace DirU { export function toString(dir: Dir): DirStr { return dirReverse[dir] } + export function isDir(dir: Dir3d): dir is Dir { + return dir <= 4 + } export function fromDir3d(dir: Dir3d): Dir { - assert(dir >= Dir3d.UP, 'Dir3d to Dir conversion error') - return dir as unknown as Dir + assert(isDir(dir), 'Dir3d to Dir conversion error') + return dir } export const allExpect = { [Dir.NORTH]: [Dir.EAST, Dir.SOUTH, Dir.WEST], diff --git a/src/util/vec2.ts b/src/util/vec2.ts index 6a5a6cb..a26b262 100644 --- a/src/util/vec2.ts +++ b/src/util/vec2.ts @@ -42,7 +42,7 @@ export namespace Vec2 { return res } - export function subC(v1: Vec2, x: number, y: number, copy?: boolean) { + export function subC(v1: Vec2, x: number, y?: number, copy?: boolean) { const res: any = copy ? {} : v1 y = y === undefined || y === null ? x : y res.x = (v1.x || 0) - (x || 0)