diff --git a/.vscode/settings.json b/.vscode/settings.json index 009ea62..bbeb372 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,15 +6,13 @@ "gravitable", "mult", "toolbelt", + "Tsify", "tylercraft", "upsert", "vecs", "wasd" ], "typescript.tsdk": ".yarn/sdks/typescript/lib", - "files.exclude": { - // "bin/": true - }, "rust-analyzer.linkedProjects": ["lib/world/Cargo.toml"], "search.exclude": { "**/node_modules": true, @@ -26,5 +24,10 @@ }, "editor.suggestSelection": "first", "eslint.nodePath": ".yarn/sdks", - "typescript.enablePromptUseWorkspaceTsdk": true + "editor.defaultFormatter": "dbaeumer.vscode-eslint", + + "typescript.enablePromptUseWorkspaceTsdk": true, + "[typescript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + } } diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 0000000..dffe4d3 --- /dev/null +++ b/.zed/settings.json @@ -0,0 +1,9 @@ +// Folder-specific settings +// +// For a full list of overridable settings, and general information on folder-specific settings, +// see the documentation: https://zed.dev/docs/configuring-zed#settings-files +{ + "rust-analyzer": { + "linkedProjects": ["./lib/world/Cargo.toml"] + } +} diff --git a/DEVLOG.md b/DEVLOG.md index 17c99f1..2632103 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1,18 +1,166 @@ +# 01_24_26 + +Working on loading chunks with the server. I started to launch chunk requests in the background so I don't have to await on the consume single chunk request. + +Looks like multiplayer is working. But the client and server are hopelessly out of sync. I also don't know why the client is so slow, I need to figure that out. That should help. But really I need to add deltas to the update functions and I need to have the server sync the position with the client. + +# 01_11_26 + +Worked on the starting flow for making a client and server game. The joining and starting of a game seems to have some race condition because I have to refresh the page to actually join. + +Need to figure out this flow more + +# 09_14_25 + +Yesterday I got the menu and saving stuff working much better. I'm pretty happy with how everything works now. I also restructred a lot of things and made chunk mesh rendering much quicker. I might want to move to some sort of shared memory thing for inserting chunks. I'm not sure why it is so slow still. + +Goals for today + +- Get multiplayer working again. +- Add an options screen for launching new games +- Speed up chunk loading again + +# 09_13_25 + +I need to get the PR out, here are the remaining things to do + +- Ensure the game scripts thing works +- Get mobile working +- Battle Test the server +- Add a single new fun game script: Falling blocks, the world blocks start falling and you have to jump to stay as high as possilbe + +Then deploy this! + +# 08_30_25 + +It's been a bit but I'm back. I've mostly been working on getting scripts to be serialzied. It is hard to get the wasm scripts to live in rust. + +I'm currently trying to load the scripts and everything is moving forward. + +I probably want to move to a similar structure as the Entities soon where a GameScript is a struct instead of a trait + +# 06_03_25 + +I've worked more on optimizing the chunk insertion code. The release build of the app is much faster now and I'm happy with it. + +I broke up the game updating code into a bunch of functions that I can run seperately and that is nice. + +Next I want to work on setting the options for the game when you start it. + +I think I can make it so options can be changed at run time. + +# 06_02_25 + +I got the server working again. I want to fix chunk loading now, the chunks around me load in such a strange way, I can walk up to chunks and not have them load and I don't know why. + +I've been profiling the code that inserts chunks, it isn't as optimal as it coudl be, but when I build in release mode it is pretty fast still on my computer when I have a full world generation. I think I shoudl maybe optimize the chunk insertion code a little bit still. + +Okay, I brought the chunk insertion time down from around 30ms to 12ms. The biggest thing was removing hash maps and using arrays instead. I hate how slow rust hashmaps are. + +# 05_27_25 + +I reworked the entity serialiaztion yesterday and I'm so happy with it now. Now I'm working on adding the fireballs back. They are working but they don't destory anything yet, I need to make them destroy blocks and hurt players. + +What happens if you die? Maybe you just teleport back to the spawn. + +Okay, now I'm testing the server again. I've found a couple errors and a lot fo files that didn't build. Now I'm getting an issue with the entity serialization, the components are not being serialized when being saved to the db. Idk what is going on. + +# 05_26_25 + +I made the UI yesterday and it is coming along. I need to figure out what to do next. I think making the belt work seems good. +I also want to add back the fireball entity that breaks a block or injures a player. Then the players have health and they can get more health by eating a food item. + +I also need to test the terrain generation and make that work better.I also need to add a button for saving while in single player mode. + +# 05_25_25 + +I've fixed up the server now and multiplayer seems to work. I can now also add blocks to the game again. I don't know what is left for things that I'm confused about, maybe I should just start cleaning everything up now. Could work on mobile development as well. + +List of things to do for single player: + +- Add gravity and creative mode +- Fix movement controls +- Add back third person view + +Claude found a bug that let the player fall through the world and came up with a good fix. That is crazy. + +There are still times where the player can go through the world a little and I'm not sure why it happens. It is very rare. But now jumping and gravity works well. + +Okay, I have fixed the movement. This is the best I have ever had it. I can run around complicated block structures and not clip through them or teleport. I had to do a better sorting system where I sorted by the amount a collision would move me, not how close one of my faces was to the collision. + +# 05_21_25 + +I've worked on making the server runner. I'm relizing it doesn't make a lot of sense to serpatate out the sp-game-serivce and the runner. The cut between them isn't that clean. I will just make two different runners and then see what logic I need to abstract to make a good UI. + +I've been thinking about the chunk flow. The server will be loading chunks with its sandbox game script, the client will also being doing this, but the client requests the chunks from the server instead of the terrain gen. This means the client could request a chunk too soon, but I shoudl probalby just load all the chunks around a player before they join? Maybe I can send them updates via sockets about what the server is doing. + +I need to bring back fun loading spinners + +Also the game shoudl have the property of chunkRequestor, not the client. The sandbox script shoudl be renamed to "loadchunksaroundentity" script and returns load requests to the game. The game then calls the request function on all chunks that the scripts returned, then the client will get from the server and give them to the local game and it will insert the chunks one by one. + +## 05_19_25 + +We now can serialize the game state and save it to indexdb. It took a while to figure out how to serialize the entities. I went down a rabbit hole trying to get to work, but it doesn't support wasm-bindgen. I ended up just assuming everything was a player for now. + +I've taken the strategy of "find the hardest problem and work on that until you know you can come back later and clean it up". + +I've been thinking about how I can turn this into an RL training system. I'm pretty excited to try to do that. + +The next hardest thing to me seems to be the server. It seem more complicated to me than it needs to be. This is how I think it should work: + +- The server the game on a loop, anytime the game state changes it will be broadcast to all the clients. +- The server can change either because the game performs an action (like spawning an entity) or because the clients send actions to the server. + But I think there is a problem: If the game sends all of these diffs to the client, it will send an update to the client for every single action. That will be too much since the clients can compute the velocity themselves. + +I think a good solution to this is to have "script actions" that are generated by game scripts. Then the server can mark the scripts whose actions will be sent to the client. +That way it can exclude scripts like "MovePlayer" but include ones like "SpawnCows" and then the client would not use the SpawnCow script. + +I don't think we need to concept of "script actions". The scripts return GameDiffs in there update functions. I can just mark certain scripts to not have their diffs sent to the client. + +This way "actions" are things that are predictable updates that are only made by clients. They can be sent over the wire. Scripts are logic that updates the game state in some way but may or may not be sent to the client. + +Now when we receive an action from a client, we immediately apply it to the game state and send it to everyone. Then in the server update function, we run the game update, and send the diffs to the clients for only the scripts we want. + +The client won't run the SandboxScript. The server will and it will just load chunks around the player. The player renderer then requests the chunks around the player. The render distance should be less than the load distance. So we shouldn't request chunks that aren't loaded. The get chunk logic should likely be moved to a rest endpoint. + +Maybe I can use trpc to have everything be typed. + +The game-service.ts, players.ts, and server-game.ts should all be combined into a single file. + +I made a new SeverGameManager that i smuch much simplier. I'll have to move the game fetching and saving logic somewhere but it is nice. + +I think I want it to be the case that players that aren't online are still entites in the game, they are just not moving. + +That way I don't have to send welcome messages to everyone when they join. (But I still can for an "online" status) that would just need to be handled by the server instead of the engine and the clients would have differnet state. + +Okay, everything is looking better. I haven't tested a thing but I'm going to go to sleep. I need to make a "server-runner" soon that copies a lot of the current runner but has different game scripts and sends actions to the server + +## 05_18_25 + +This repo is in a messy state. It seems like a a lot of work is needed to clean it up. I think I was refactoring to have all of the entity logic in the rust code instead and I was half way through that. I think I'mm going to make a very simple +UI to begin with that uses the rust code and attempts to render everything instead of messing with the server stuff for now. + +I got the actions to work in the UI. They are saved and updated. But the chunk rendering is a mess and isn't working. + +Did a lot of work today making everything work with the UI. The wrapper isn't really needed as much anymore. I was half way through getting serializing to work but it isn't really done yet, some values aren't being saved to the DB. + ## 07_11_24 -Spent a while trying to figure out why cargo randomly rebuilt dependencies. Figured out it was turbo's issue? So I removed turbo and moved to just using yarn. -I also love the game script idea. It is cleaning things up nicely. +Spent a while trying to figure out why cargo randomly rebuilt dependencies. Figured out it was turbo's issue? So I removed turbo and moved to just using yarn. +I also love the game script idea. It is cleaning things up nicely. ## 06_22_24 -Trying to get the collision detection to be better with the player and the world. + +Trying to get the collision detection to be better with the player and the world. Current plan: -- Make a lib funciton that takes a box (pos, dim) and a pos it wants to go to and return the position it can actually go to. If the box would hit something while moving to the new position, then find the shorted distance to make the box not collide with anything. + +- Make a lib funciton that takes a box (pos, dim) and a pos it wants to go to and return the position it can actually go to. If the box would hit something while moving to the new position, then find the shorted distance to make the box not collide with anything. Basic form of function: -- Take all the world points of the block corner and the world points of the new potition. Create a line segment for each of these. Make a function that determines if a line segment is intersecting the world and at which point it intersects. Then find the line segment that minimizes the distance traveled and update all the box positions with that and return the new position and the face that it hit. Only stop applying force to a player if they hit something below them. +- Take all the world points of the block corner and the world points of the new potition. Create a line segment for each of these. Make a function that determines if a line segment is intersecting the world and at which point it intersects. Then find the line segment that minimizes the distance traveled and update all the box positions with that and return the new position and the face that it hit. Only stop applying force to a player if they hit something below them. ## Some other date @@ -138,8 +286,6 @@ Real issue seems to be that wasm_pack writes twice. It now renders the chunks made in rust to the screen using the chunk mesh. Looks like it is including a couple extra faces that aren't needed but that can be fixed with time. - - # 2 / 15 / 23 I've still been working here and there. Found a bug in the ray detection on the plane level. Test should be failing need to figure out why. @@ -159,6 +305,7 @@ I think a better debug mode to aim to make is a way to have no chunks loaded, bu Maybe also make it where the block face that is being looked at is highlighted I guess to hot reload I could have something that looks like this + ``` if (hot) { const state = game.save() @@ -169,7 +316,6 @@ if (hot) { Got the placing of a debug block working, just have to figure out how to place the block when there are no chunks. Do I want to check on the client if the chunk exists before inserting or add an option to automatically create the chunk if one doesn't exist. - # 6 / 10 / 23 Seems like deleting a block doesn't update the mesh. @@ -180,90 +326,78 @@ My idea to fix this is to add a dirty array to the chunk that is updated when a That fixed it but it does not delete the dirty blocks in a chunk ever. - Seems to still be an issue with placing blocks. Sometimes a a block seems to be not found and the ray goes through it. Only seems to happen when x or y cord is negative. Also might need to have a script that adds `type: module` to the package json in the wasm folder. That is preventing nodejs from loading the wasm module. - Think I want to work on high lighting the block that is being looked at for debug purposes. It will help with this stuff a lot. Looks like the blocks that aren't being found are because the ray isn't even checking that block sometimes. Found the issue. I made the ray check many more blocks while marching and it finds the correct one now. - It is now able to be built and deployed. But there seems still be be some minor issues + - infinite terrain generation doesn't work - Transparent blocks have some issues - Textures are rotated incorrectly - Working on infinite chunk generation. I want to make it so a single chunk is rendered a frame. I made it where it now only sends a single chunk at a time to be loaded. - # 6 / 11 / 23 Added turbo repo and linting to the project. Moved everything around to make more sense and I think it is a good structure. Want to work on fixing terrain gen next. - # 6 / 15 / 23 Multiplayer kind of works not but is not robust at all. And all the textures are rotated incorrectly. - Trying to think about the best way to have an entity be controlled by gpt4. Might want an "EntityController" that moves the entity around. Entities might have a "brain" that is passed in that controls the entity. Maybe each entity needs a controller. The entity class controls the logic of the entity and the moves it can make. The controller calls those moves in interesting ways. The entity controller for a player might be a socket, a keyboard, or gpt4. type entityController = { - entity: Entity - update: () => void +entity: Entity +update: () => void } - examples keyboardPlayerController { - setup() { - // start event listeners for fast events - } - update() { - call some entity moves - } +setup() { +// start event listeners for fast events +} +update() { +call some entity moves +} } socketPlayerController { - setup() { - // start socket listeners - } - update() { - call some entity moves - } +setup() { +// start socket listeners +} +update() { +call some entity moves +} } - # 08/23/23 Thinking of what to work on next. I think rewritting the terrain generator in rust could be a good project - # 09/03/23 -I've got covid, so I've had time to rewrite this is rust a bit. I've created a terrain gen app that does smooth height transitions, generates trees, and generates flowers. Making the trees be spread a part randomly is hard, but I solved it by doing it chunk by chunk and lazily loading the tree in nearby chunks to make sure there is no overlap. +I've got covid, so I've had time to rewrite this is rust a bit. I've created a terrain gen app that does smooth height transitions, generates trees, and generates flowers. Making the trees be spread a part randomly is hard, but I solved it by doing it chunk by chunk and lazily loading the tree in nearby chunks to make sure there is no overlap. I noticed that the transparency is broken and that some of the textures are rotated incorrectly. I think I will fix that next. - - # 09/04/23 -Fixed transparency, it was an issue with the new way I'm doing mesh generation. Fixed textured being rotated incorrectly too. Now noticing that a tree's leafs are not included if they go over a chunk boundary. Tackling that next. - -Then I'll start thinking about biomes. +Fixed transparency, it was an issue with the new way I'm doing mesh generation. Fixed textured being rotated incorrectly too. Now noticing that a tree's leafs are not included if they go over a chunk boundary. Tackling that next. +Then I'll start thinking about biomes. # 03/19/23 diff --git a/Events.md b/Events.md new file mode 100644 index 0000000..43a36b0 --- /dev/null +++ b/Events.md @@ -0,0 +1,34 @@ + +The game has many scripts. The scripts control entities in the game. + +Scripts have a list of actions that can be taken on them. These actions can be serilaized and sent over a server. +Example +(entityId, action, data) = ("player1", "move", "left") + +You can query a player for all of its actions + +Script data is not serilaized + +Example Scripts +JumpScript, +MoveScript, +GravityScript, + + + +Flow of events for user pressing space: +- JS creates a jump event +- Jump event sent over the wire (either to server or worker) +- Game recieves jump events and finds script for it +- Script looks up the event and executes it + + + +Player Places block: +- Js creates a place block event +- Sent over wire +- Game recieves place block event and finds script for it +- Script looks up the event and executes it +- Chunks have been updateds so JS game scripts are called + + diff --git a/apps/server/db.ts b/apps/server/db.ts deleted file mode 100644 index 462534b..0000000 --- a/apps/server/db.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { IGameMetadata, ISerializedGame } from "@craft/engine"; -import { Collection, Document, MongoClient } from "mongodb"; - -export interface IDbManager { - getAllGameMetadata(): Promise; - getGame(gameId: string): Promise; - saveGame(game: ISerializedGame): Promise; - deleteGame(gameId: string): Promise; -} - -export class DBManager implements IDbManager { - static async makeClient() { - const DB_URL = process.env.DB_URL; - if (!DB_URL) { - throw new Error("DB_URL not defined"); - } - console.log("Connecting to database"); - const client = await MongoClient.connect(DB_URL); - console.log("Connected to database 🎉"); - return new DBManager(client); - } - - private gameCollection: Collection; - - private constructor(private client: MongoClient) { - this.gameCollection = this.client.db("games").collection("games"); - } - - getAllGameMetadata(): Promise { - return this.gameCollection - .find( - {}, - { - projection: { - gameId: 1, - name: 1, - }, - } - ) - .toArray(); - } - - getGame(gameId: string): Promise { - return this.gameCollection.findOne({ gameId }); - } - - async saveGame(game: ISerializedGame) { - await this.gameCollection.updateOne( - { gameId: game.gameId }, - { $set: game }, - { upsert: true } - ); - } - - async deleteGame(gameId: string) { - await this.gameCollection.deleteOne({ gameId }); - } -} diff --git a/apps/server/game-service.ts b/apps/server/game-service.ts deleted file mode 100644 index b12f5ed..0000000 --- a/apps/server/game-service.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { - Game, - ICreateGameOptions, - ISerializedGame, - ISocketMessageType, - SandboxGScript, - SocketMessage, - setConfig, -} from "@craft/engine"; -import { ServerGameScript } from "./server-game.js"; -import Websocket from "ws"; -import { IDbManager } from "./db.js"; -import SocketServer from "./socket.js"; - -export class TimerRunner { - private lastTime = Date.now(); - - constructor(private game: Game) { - setInterval(this.update.bind(this), 1000 / 40); - } - - update() { - const now = Date.now(); - const diff = now - this.lastTime; - // if we leave the tab for a long time delta gets very big, and the play falls out of the world. - // I'm just going to make them not move for now, but I need to remove make the system more tollerant of large deltas - if (diff > 100) { - console.log("Skipping update, time diff is too large", diff); - this.lastTime = now; - return; - } - this.game.update(diff); - this.lastTime = now; - } -} - -export class GameService { - private games: Map = new Map(); - - constructor( - private dbManager: IDbManager, - private socketInterface: SocketServer - ) { - this.socketInterface.listenForConnection((ws: Websocket) => { - this.socketInterface.listenTo(ws, (message) => { - this.handleSocketMessage(message, ws) - .then(() => void 0) - .catch((e) => { - console.log("Error handling socket message", message, e); - }); - }); - }); - } - - private async buildGame( - id: string, - options: ICreateGameOptions | ISerializedGame - ): Promise { - const gameSaver = { - save: async (game: Game) => { - await this.dbManager.saveGame(game.serialize()); - }, - }; - - const game = Game.make(options, gameSaver); - - game.addGameScript(ServerGameScript, this.socketInterface); - - game.addGameScript(SandboxGScript); - - await game.setupScripts(); - - console.log("Starting game", id, game.stateDiff.get()); - - new TimerRunner(game); - - this.games.set(id, game); - - return game; - } - - async handleSocketMessage(message: SocketMessage, ws: Websocket) { - if (message.isType(ISocketMessageType.joinWorld)) { - const { worldId, myUid } = message.data; - console.log("Got join world message", worldId, myUid); - - const game = await this.getWorld(worldId); - if (!game) { - console.log("That world doesn't exist", worldId); - - this.socketInterface.send( - ws, - new SocketMessage(ISocketMessageType.worldNotFound, {}) - ); - - return; - } - - const serverGameScript = game.getGameScript(ServerGameScript); - - // this function sends a welcome message to the client - serverGameScript.addSocket(myUid, ws); - } else if (message.isType(ISocketMessageType.newWorld)) { - const payload = message.data; - const game = await this.createGame(payload); - const serverGameScript = game.getGameScript(ServerGameScript); - console.log("Create Id: ", game.gameId); - serverGameScript.addSocket(payload.myUid, ws); - } else if (message.isType(ISocketMessageType.saveWorld)) { - const payload = message.data; - const game = this.games.get(payload.worldId); - if (!game) { - console.log("That world doesn't exist", payload); - return; - } - await this.dbManager.saveGame(game.serialize()); - } - } - - async getWorld(gameId: string): Promise { - console.log("Getting game", gameId); - - const foundGame = this.games.get(gameId); - if (foundGame) { - console.log("Found game in memory"); - return foundGame; - } - - const dbGame = await this.dbManager.getGame(gameId); - if (!dbGame) { - console.log("Game not found"); - return null; - } - - return this.buildGame(gameId, dbGame); - } - - async getAllWorlds() { - return this.dbManager.getAllGameMetadata(); - } - - async createGame(options: ICreateGameOptions): Promise { - console.log("Creating game with options", options); - - setConfig(options.config); - - const id = String(Math.random()); - - return this.buildGame(id, options); - } -} diff --git a/apps/server/players.ts b/apps/server/players.ts deleted file mode 100644 index f71a4bb..0000000 --- a/apps/server/players.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { - Game, - GameStateDiff, - ISocketMessageType, - Player, - PlayerAction, - PlayerActionService, - SocketMessage, -} from "@craft/engine"; -import WebSocket from "ws"; -import SocketServer from "./socket"; - -export default class Players { - players: Map = new Map(); - - private playerActionsService: PlayerActionService; - - constructor(public game: Game, private socketInterface: SocketServer) { - this.playerActionsService = new PlayerActionService(this.game); - } - - getSockets(): WebSocket[] { - return Array.from(this.players.keys()); - } - - sendMessageToAll(message: SocketMessage, exclude?: WebSocket) { - console.log("Sending message to all", message); - for (const socket of this.players.keys()) { - if (exclude && socket === exclude) continue; - this.socketInterface.send(socket, message); - } - } - - addPlayer(uid: string, ws: WebSocket): void { - // generate a random ID for the new player - - // send a welcoming message to the new player - const welcomeMessage = new SocketMessage(ISocketMessageType.welcome, { - uid, - game: this.game.serialize(), - }); - this.socketInterface.send(ws, welcomeMessage); - - const player = this.game.addPlayer(uid); - - // add them to the SYSTEM - this.players.set(ws, player); - - // listen for changes from the player - const listener = (message: SocketMessage) => { - if (message.isType(ISocketMessageType.playerActions)) { - const playerAction = new PlayerAction( - message.data.type, - message.data.data - ); - this.onPlayerAction(ws, playerAction); - } - }; - this.socketInterface.listenTo(ws, listener); - - const gameDiff = new GameStateDiff(this.game); - gameDiff.addEntity(uid); - - console.log("Alerting about new guy"); - - // tell Everyone about the new guy - this.sendMessageToAll( - new SocketMessage(ISocketMessageType.gameDiff, gameDiff.get()), - ws - ); - - // If they leave, KILL THEM - ws.on("close", this.removePlayer.bind(this, ws)); - - console.log( - `New player! ${uid} ${ - this.game.entities.getActivePlayers().length - } players` - ); - } - - removePlayer(ws: WebSocket): void { - const player = this.players.get(ws); - - if (!player) { - return; - } - - const gameDiff = new GameStateDiff(this.game); - gameDiff.removeEntity(player.uid); - - // tell everyone about this tragedy - this.sendMessageToAll( - new SocketMessage(ISocketMessageType.gameDiff, gameDiff.get()), - ws - ); - - console.log( - "Player left", - player.uid, - this.game.entities.getActivePlayers().length - ); - - // FINISH THEM! - this.game.entities.removePlayer(player.uid); - this.players.delete(ws); - - console.log( - `Remove Player! ${this.game.entities.getActivePlayers().length} players` - ); - } - - onPlayerAction(ws: WebSocket, playerAction: PlayerAction) { - const player = this.players.get(ws); - if (!player) { - return; - } - this.playerActionsService.performAction(playerAction); - - // tell everyone about the new action - this.sendMessageToAll( - new SocketMessage( - ISocketMessageType.playerActions, - playerAction.getDto() - ), - ws - ); - } -} diff --git a/apps/server/server-game.ts b/apps/server/server-game.ts deleted file mode 100644 index 321aad6..0000000 --- a/apps/server/server-game.ts +++ /dev/null @@ -1,137 +0,0 @@ -import Players from "./players.js"; -import WebSocket from "ws"; -import { - Game, - GameAction, - GameStateDiff, - ISocketMessageType, - MapArray, - Vector2D, - SocketMessage, - setConfig, - ISerializedChunk, - GameScript, -} from "@craft/engine"; -import SocketServer from "./socket.js"; - -export class ServerGameScript extends GameScript { - name = "server"; - - public clients: Players; - public actionMap: MapArray = new MapArray(); - - constructor(game: Game, private socketInterface: SocketServer) { - super(game); - // Remove all players since none are connected yet - game.entities.removeAllPlayers(); - - setConfig(game.config); - - this.clients = new Players(game, socketInterface); - } - - onGameStateDiff(diff: GameStateDiff): void { - const stateDiff = diff.copy(); - - // Set the config for the game (This is a hack since the config is global) - setConfig(this.game.config); - - // Send the initial state diff to all clients - // This state diff has no client sent actions so it should - // only be passive things (An entity spawning) - if (stateDiff.hasData()) { - console.log("Sending initial diff"); - this.clients.sendMessageToAll( - new SocketMessage(ISocketMessageType.gameDiff, stateDiff.get()) - ); - } - - stateDiff.clear(); - - // Run through each client's actions and save the combined state diff - // from the other client's actions. Combining them lets us send all client - // updates as one socket message. - - // Set the initial state diff for each client - const clientDiffs = new Map(); - for (const ws of this.clients.getSockets()) { - clientDiffs.set(ws, stateDiff.copy()); - } - - if (this.actionMap.size > 0) { - for (const actions of this.actionMap.values()) { - console.log("Actions", actions); - } - } - - for (const [ws, actions] of this.actionMap.entries()) { - stateDiff.clear(); - - // Handle all the actions. The new diff should only have updates - // for the player who made them and chunk they might have affected - for (const action of actions) { - this.game.handleAction(action); - } - - console.log("Diff after actions", stateDiff.get()); - - // Append the diff to all clients but the one that sent the actions - this.clients - .getSockets() - .filter((s) => s !== ws) - .forEach((s) => { - clientDiffs.get(s)?.append(stateDiff); - }); - } - - // Send the combined state diff to all clients - for (const [ws, diff] of clientDiffs.entries()) { - if (diff.hasData()) { - const diffData = diff.get(); - console.log("Sending diff", diffData); - this.socketInterface.send( - ws, - new SocketMessage(ISocketMessageType.gameDiff, diffData) - ); - } - } - - this.actionMap.clear(); - } - - private async sendChunkTo(chunkPosString: string, ws: WebSocket) { - // Set the config for the game (This is a hack since the config is global) - setConfig(this.game.config); - const world = this.game.world; - console.log("ServerGame: Sending chunk to player: ", chunkPosString); - const chunkPos = Vector2D.fromIndex(chunkPosString); - let chunk: ISerializedChunk | null = null; - if (world.hasChunk(chunkPos)) { - chunk = world.getChunkFromPos(chunkPos); - } else { - // chunk = await world.loadChunk(chunkPos); - } - if (!chunk) throw new Error("Chunk wasn't found"); - this.socketInterface.send( - ws, - new SocketMessage(ISocketMessageType.setChunk, { - pos: chunkPosString, - data: chunk, - }) - ); - } - - addSocket(uid: string, ws: WebSocket): void { - this.clients.addPlayer(uid, ws); - - this.socketInterface.listenTo(ws, (message) => { - console.log("Got Message", message); - if (message.isType(ISocketMessageType.actions)) { - const gameAction = new GameAction(message.data.type, message.data.data); - this.actionMap.append(ws, gameAction); - } else if (message.isType(ISocketMessageType.getChunk)) { - this.sendChunkTo(message.data.pos, ws); - } - }); - } -} diff --git a/apps/server/server.ts b/apps/server/server.ts deleted file mode 100644 index d5481bb..0000000 --- a/apps/server/server.ts +++ /dev/null @@ -1,43 +0,0 @@ -import express from "express"; -import { Request, Response } from "express"; -import { WebSocketServer } from "ws"; -import cors from "cors"; -import { TerrainGenModule, WorldModule } from "@craft/engine"; -import SocketServer from "./socket.js"; -import { GameService } from "./game-service.js"; -import { FileDb } from "./file-db.js"; - -const PORT = process.env.PORT ?? 3000; - -const app = express(); - -app.use(cors()); -app.use(express.urlencoded({ extended: false })); -app.use(express.json({ limit: "50mb" })); - -const webClientPath = new URL("../../web-client/dist", import.meta.url) - .pathname; -console.log("Serving web client, path: ", webClientPath); -app.use(express.static(webClientPath)); - -// const db = await DBManager.makeClient(); -const fileDb = new FileDb(); - -const server = app.listen(PORT, () => - console.log(`Server running on port ${PORT} 🚀`) -); -const wss = new WebSocketServer({ server }); - -const socketService = new SocketServer(wss); - -await WorldModule.load(); -await TerrainGenModule.load(); - -const gameService = new GameService(fileDb, socketService); - -app.get("/worlds", async (_req: Request, res: Response) => { - const worlds = await gameService.getAllWorlds(); - res.send(worlds); -}); - -console.log("Server started"); diff --git a/apps/server/src/db.ts b/apps/server/src/db.ts new file mode 100644 index 0000000..c526086 --- /dev/null +++ b/apps/server/src/db.ts @@ -0,0 +1,83 @@ +import { + IApiGameMetadata, + ISerializedGame, + serializeGame, +} from "@craft/engine"; +import { CreateGameOptions, Game } from "@craft/rust-world"; +import { Collection, Document, MongoClient } from "mongodb"; + +export class GameDb { + static async makeClient() { + const DB_URL = process.env.DB_URL; + if (!DB_URL) { + throw new Error("DB_URL not defined"); + } + console.log("Connecting to database"); + const client = await MongoClient.connect(DB_URL); + console.log("Connected to database 🎉"); + return new GameDb(client); + } + + private gameCollection: Collection; + + private constructor(private client: MongoClient) { + this.gameCollection = this.client.db("tylercraft").collection("games"); + } + + getAllGameMetadata(): Promise { + return this.gameCollection + .find( + {}, + { + projection: { + gameId: 1, + name: 1, + }, + } + ) + .toArray(); + } + + async getGame(gameId: string): Promise { + const data: ISerializedGame | null = + await this.gameCollection.findOne({ gameId }); + if (!data) { + return null; + } + return data; + } + + async getSerializedGame(gameId: string): Promise { + return await this.gameCollection.findOne({ gameId }); + } + + async getGameMetadata(gameId: string): Promise<{ name: string } | null> { + return await this.gameCollection.findOne<{ name: string }>( + { gameId }, + { projection: { name: 1 } } + ); + } + + async saveGame(game: Game) { + const serializedGame = serializeGame(game); + const json = JSON.stringify(serializedGame, null, 2); + const parsedGame = JSON.parse(json); + console.log("Saving game parsed", parsedGame); + console.log("Saving game json", json); + await this.gameCollection.updateOne( + { gameId: game.id }, + { $set: parsedGame }, + { upsert: true } + ); + } + + async createGame(options: CreateGameOptions): Promise { + const game = Game.create(options); + await this.saveGame(game); + return game; + } + + async deleteGame(gameId: string) { + await this.gameCollection.deleteOne({ gameId }); + } +} diff --git a/apps/server/file-db.ts b/apps/server/src/file-db.ts similarity index 93% rename from apps/server/file-db.ts rename to apps/server/src/file-db.ts index dca4420..ca0f467 100644 --- a/apps/server/file-db.ts +++ b/apps/server/src/file-db.ts @@ -1,5 +1,4 @@ import { IGameMetadata, ISerializedGame } from "@craft/engine"; -import { IDbManager } from "./db"; import fs from "fs"; const DATA_DIR = process.env.DATA_DIR || "./game-data/"; @@ -7,7 +6,7 @@ if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR); } -export class FileDb implements IDbManager { +export class FileDb { getAllGameMetadata(): Promise { const gameFiles = fs.readdirSync(DATA_DIR); return Promise.resolve( diff --git a/apps/server/src/logger.ts b/apps/server/src/logger.ts new file mode 100644 index 0000000..4808fa8 --- /dev/null +++ b/apps/server/src/logger.ts @@ -0,0 +1,5 @@ +export const makeLogger = (name: string) => { + return (...args: any[]) => { + console.log(`[${new Date().toISOString()}] ${name}: `, ...args); + }; +}; diff --git a/apps/server/src/server-game-manager.ts b/apps/server/src/server-game-manager.ts new file mode 100644 index 0000000..b189b37 --- /dev/null +++ b/apps/server/src/server-game-manager.ts @@ -0,0 +1,333 @@ +import { + Chunk, + ChunkPos, + EntityActionDto, + Game, + GameDiff, + SandBoxGScript, +} from "@craft/rust-world"; +import SocketServer from "./socket"; +import WebSocket from "ws"; +import { + deserializeGame, + ISerializedChunk, + ISerializedGame, + ISocketMessageType, + SocketMessage, +} from "@craft/engine"; +import { GameDb } from "./db"; +import { makeLogger } from "./logger.js"; +import { add_script_to_registry } from "@craft/rust-world"; + +type ClientId = number; + +const AUTO_SAVE_GAME = false; +const AUTO_SAVE_GAME_INTERVAL = 5000; +const FIXED_TIMESTEP_MS = 1000 / 60; // 16.67ms = 60 ticks per second +const FPS_LOG_INTERVAL_MS = 5000; // Log FPS every 5 seconds + +const makeGameLogger = (gameId: string) => { + return makeLogger(`ServerGameManager:${gameId}`); +}; + +class ServerGameManagerGameScript { + static name = "ServerGameManagerGameScript"; + + private updatedChunks: Set = new Set(); + + static register() { + add_script_to_registry(ServerGameManagerGameScript); + } + + onScriptMounted(allChunkIds: Set, allEntityIds: Set): void { + console.log( + "ServerGameManagerGameScript onScriptMounted", + allChunkIds, + allEntityIds + ); + } + + onChunkUpdate(chunkId: number): void { + console.log("ServerGameManagerGameScript onChunkUpdate", chunkId); + this.updatedChunks.add(chunkId); + } + + onEntityUpdate(entityId: number): void { + console.log("ServerGameManagerGameScript onEntityUpdate", entityId); + } + + getUpdatedChunks(): number[] { + const chunks = Array.from(this.updatedChunks); + this.updatedChunks.clear(); + return chunks; + } +} + +ServerGameManagerGameScript.register(); + +export class ServerGameManager { + clients: Map = new Map(); + scriptsToSendToClients: string[] = []; + timer: NodeJS.Timeout | null = null; + autoSaveTimer: NodeJS.Timeout | null = null; + is_running = false; + log: (...args: any[]) => void; + + // FPS tracking + private updateCount = 0; + private lastFpsLogTime = Date.now(); + + static async create( + gameDto: ISerializedGame, + socketService: SocketServer, + gameDb: GameDb + ): Promise { + const game = deserializeGame(gameDto); + const log = makeGameLogger(game.id); + game.ensureScript(SandBoxGScript.name()); + + game.run_scripts(FIXED_TIMESTEP_MS); + + async function task() { + await new Promise((resolve) => setTimeout(resolve, 0)); + } + + let pendingChunkCount = game.getPendingChunkCount(); + + log("Loading chunks", pendingChunkCount); + + while (pendingChunkCount > 0) { + log("Loading chunk", pendingChunkCount); + await task(); + game.add_single_chunk(); + pendingChunkCount = game.getPendingChunkCount(); + } + + return new ServerGameManager(game, socketService, gameDb); + } + + constructor( + private game: Game, + private socketInterface: SocketServer, + private gameDb: GameDb + ) { + this.log = makeGameLogger(game.id); + this.log("Creating game"); + + this.socketInterface.listenForConnection((ws) => { + this.listenForJoinRequests(ws); + }); + + game.ensureScript(ServerGameManagerGameScript.name); + game.add_all_scripts(); + } + + private getGameManagerGameScript(): ServerGameManagerGameScript { + return this.game.getScriptState( + ServerGameManagerGameScript.name + ) as ServerGameManagerGameScript; + } + + listenForJoinRequests(ws: WebSocket) { + this.socketInterface.listenTo(ws, async (message) => { + this.log("Socket message from client", message); + if (!message.isType(ISocketMessageType.joinWorld)) { + return; + } + this.log("Joining game", message.data); + const { gameId, myUid } = message.data; + if (gameId !== this.game.id) { + return; + } + + this.game.makeAndAddPlayer(myUid); + this.game.add_new_entities(); // Ensure player is added before serializing + + const entities = this.game.serializeEntities(); + this.log("Entities", JSON.stringify(entities, null, 2)); + + // load chunks around the player + this.game.run_scripts(FIXED_TIMESTEP_MS); + + async function task() { + await new Promise((resolve) => setTimeout(resolve, 0)); + } + + let pendingChunkCount = this.game.getPendingChunkCount(); + + this.log("Loading chunks", pendingChunkCount); + + while (pendingChunkCount > 0) { + this.log("Loading chunk", pendingChunkCount); + await task(); + this.game.add_single_chunk(); + pendingChunkCount = this.game.getPendingChunkCount(); + } + + // send welcome message + this.socketInterface.send( + ws, + new SocketMessage(ISocketMessageType.welcome, { + uid: myUid, + entities: entities, + }) + ); + + const entity = this.game.getEntityById(myUid); + if (!entity) { + console.error("Player not found in join request", myUid); + return; + } + + this.clients.forEach((client, _) => { + this.socketInterface.send( + client, + new SocketMessage(ISocketMessageType.newPlayer, entity.to_js()) + ); + }); + + this.listenForPlayerActions(ws, myUid); + + this.clients.set(myUid, ws); + }); + } + + listenForPlayerActions(ws: WebSocket, clientId: ClientId) { + this.socketInterface.listenTo(ws, (message) => { + this.log("Socket message from client", JSON.stringify(message)); + if (!message.isType(ISocketMessageType.actions)) { + return; + } + const action = message.data; + this.log("Received Action", JSON.stringify(action, null, 2)); + + const actionDto = EntityActionDto.from_js(action); + + this.game.handleAction(actionDto); + + // send action to all clients (except the one that sent it) + this.clients.forEach((client, uid) => { + if (uid === clientId) { + return; + } + this.socketInterface.send(client, message); + }); + }); + } + + // onGameUpdate(diff: GameDiff, scriptName: string): void { + // this.log("onGameUpdate", diff, scriptName); + + // if (this.scriptsToSendToClients.includes(scriptName)) { + // for (const client of this.clients.values()) { + // this.socketInterface.send( + // client, + // new SocketMessage(ISocketMessageType.gameDiff, diff) + // ); + // } + // } + // } + + // onChunkUpdate(chunkId: number): void { + // this.log("onChunkUpdate", chunkId); + // const diff = new GameDiff(); + // diff.add_chunk(BigInt(chunkId)); + // for (const client of this.clients.values()) { + // this.socketInterface.send( + // client, + // new SocketMessage(ISocketMessageType.gameDiff, diff) + // ); + // } + // } + + update() { + this.game.update(FIXED_TIMESTEP_MS); + this.updateCount++; + + // Log FPS periodically + const now = Date.now(); + if (now - this.lastFpsLogTime >= FPS_LOG_INTERVAL_MS) { + const elapsed = (now - this.lastFpsLogTime) / 1000; + const fps = this.updateCount / elapsed; + this.log(`Server FPS: ${fps.toFixed(1)}`); + this.updateCount = 0; + this.lastFpsLogTime = now; + } + + // send game diff to clients + const updatedChunks = this.getGameManagerGameScript().getUpdatedChunks(); + if (updatedChunks.length > 0) { + const diff = new GameDiff(); + for (const chunkId of updatedChunks) { + diff.add_chunk(BigInt(chunkId)); + } + const diffJs = diff.to_js(); + console.log("Sending game diff", diffJs); + + for (const client of this.clients.values()) { + this.socketInterface.send( + client, + new SocketMessage(ISocketMessageType.gameDiff, diffJs) + ); + } + } + } + + start() { + this.log("Starting game"); + this.is_running = true; + if (this.timer) { + clearInterval(this.timer); + } + this.timer = setInterval(() => { + this.update(); + }, 1000 / 60); + + if (AUTO_SAVE_GAME) { + if (this.autoSaveTimer) { + clearInterval(this.autoSaveTimer); + } + this.autoSaveTimer = setInterval(() => { + this.log("Saving game"); + this.save(); + }, AUTO_SAVE_GAME_INTERVAL); + } + } + + stop() { + this.is_running = false; + if (this.timer) { + clearInterval(this.timer); + this.timer = null; + } + if (this.autoSaveTimer) { + clearInterval(this.autoSaveTimer); + this.autoSaveTimer = null; + } + } + + getOrRequestChunk(x: number, y: number): ISerializedChunk | null { + const chunkPos = new ChunkPos(x, y); + try { + const chunk = this.game.getChunk(chunkPos); + const serializedChunk = chunk.serialize(); + return serializedChunk; + } catch (error) { + this.game.request_chunk(chunkPos); + this.log("Requested chunk", chunkPos); + return null; + } + } + + getOnlinePlayers(): number { + return this.clients.size; + } + + getSerializedEntities(): unknown { + return this.game.serializeEntities(); + } + + save() { + this.gameDb.saveGame(this.game); + } +} diff --git a/apps/server/src/server.ts b/apps/server/src/server.ts new file mode 100644 index 0000000..70a5c99 --- /dev/null +++ b/apps/server/src/server.ts @@ -0,0 +1,131 @@ +import express from "express"; +import { Request, Response } from "express"; +import { WebSocketServer } from "ws"; +import cors from "cors"; +import SocketServer from "./socket.js"; +import { ServerGameManager } from "./server-game-manager.js"; +import { GameDb } from "./db.js"; +import { IApiGameMetadata } from "@craft/engine"; +import { CreateGameOptions } from "@craft/rust-world"; +import { makeLogger } from "./logger.js"; + +const PORT = process.env.PORT ?? 3000; +const webClientPath = new URL("../../web-client/dist", import.meta.url) + .pathname; + +console.log("Config", { PORT, webClientPath }); + +const log = makeLogger("server.ts"); + +const app = express(); +const games: Map = new Map(); +const gameDb = await GameDb.makeClient(); + +const server = app.listen(PORT, () => + console.log(`Server running on port ${PORT} 🚀`) +); + +const wss = new WebSocketServer({ server }); +const socketService = new SocketServer(wss); + +app.use(cors()); +app.use(express.urlencoded({ extended: false })); +app.use(express.json({ limit: "50mb" })); + +app.use(express.static(webClientPath)); + +app.get("/games", async (_req: Request, res: Response) => { + const gamesMetadata = await gameDb.getAllGameMetadata(); + + const gameInfos: (IApiGameMetadata & { + isRunning: boolean; + onlinePlayers: number; + })[] = gamesMetadata.map((gameMetadata) => { + const game = games.get(gameMetadata.gameId); + return { + ...gameMetadata, + isRunning: game ? game.is_running : false, + onlinePlayers: game ? game.getOnlinePlayers() : 0, + }; + }); + + res.send(gameInfos); +}); + +app.post("/game", async (req: Request, res: Response) => { + const body = req.body; + log("Creating game", body); + const options = CreateGameOptions.from_js(req.body); + const game = await gameDb.createGame(options); + log("Game created", game.id); + res.send(game.id); +}); + +app.post("/game/:id/start", async (req: Request, res: Response) => { + const { id } = req.params; + log("Starting game", id); + const localGame = games.get(id); + if (localGame && localGame.is_running) { + res.status(404).send("Game already running"); + return; + } + log("Getting game", id); + const gameDto = await gameDb.getGame(id); + if (!gameDto) { + res.status(404).send("Game not found"); + return; + } + + let game: ServerGameManager | null = null; + try { + game = await ServerGameManager.create(gameDto, socketService, gameDb); + } catch (error) { + log("Error creating game", error); + res.status(500).send("Error creating game"); + return; + } + + games.set(id, game); + game.start(); + res.send("Game started"); +}); + +app.get("/game/:id/chunk/:x/:y", async (req: Request, res: Response) => { + const { id, x, y } = req.params; + const game = games.get(id); + if (!game) { + res.status(404).send("Game not found"); + return; + } + const xInt = parseInt(x); + if (isNaN(xInt)) { + res.status(400).send("Invalid x"); + return; + } + const yInt = parseInt(y); + if (isNaN(yInt)) { + res.status(400).send("Invalid y"); + return; + } + const chunk = game.getOrRequestChunk(xInt, yInt); + if (!chunk) { + res.status(404).send({ message: "Chunk requested" }); + return; + } + res.send(chunk); +}); + +// Entity sync endpoint for client-server comparison +app.get("/game/:id/entities", async (req: Request, res: Response) => { + const { id } = req.params; + const game = games.get(id); + if (!game) { + res.status(404).send("Game not found"); + return; + } + + const entitiesJs = game.getSerializedEntities(); + res.json(entitiesJs); +}); + +console.log("Server started"); diff --git a/apps/server/socket.ts b/apps/server/src/socket.ts similarity index 84% rename from apps/server/socket.ts rename to apps/server/src/socket.ts index dcda1cc..886c4a9 100644 --- a/apps/server/socket.ts +++ b/apps/server/src/socket.ts @@ -15,10 +15,19 @@ export default class SocketServer { listenForConnection(listener: ConnectionListener): void { this.connectionListeners.push(listener); + for (const ws of this.server.clients) { + listener(ws); + } } newConnection(ws: WebSocket, request: IncomingMessage): void { - const queryParams = URL.parse(request.url!, true).query; + const url = request.url; + if (!url) { + console.error("No URL in request"); + return; + } + + const queryParams = URL.parse(url, true).query; // only accept socket connections if they were meant for me if (queryParams["app"] !== "tylercraft") { @@ -34,6 +43,7 @@ export default class SocketServer { listenTo(ws: WebSocket, func: MessageListener): void { ws.on("message", (data: string) => { + console.log("Received socket message", data); const message: SocketMessageDto | undefined = (() => { try { return JSON.parse(data) as SocketMessageDto; diff --git a/apps/server/tsconfig.json b/apps/server/tsconfig.json index fce174d..7d1b91c 100644 --- a/apps/server/tsconfig.json +++ b/apps/server/tsconfig.json @@ -6,7 +6,7 @@ "module": "esnext", "moduleResolution": "node" }, - "include": ["./**/*.ts"], + "include": ["src/**/*.ts"], "exclude": ["dist/**"], "references": [{ "path": "../../lib/engine" }] } diff --git a/apps/web-client/index.html b/apps/web-client/index.html index 0996c51..769dcb2 100644 --- a/apps/web-client/index.html +++ b/apps/web-client/index.html @@ -1,100 +1,63 @@ TylerCraft - - + - -
- -
- -

Tyler Craft

-

A 3D sandbox by Tyler Tracy

-
-
- + +
+
+ + + + + + -
- - -
- - - -
-
-
-
- -
- 0,0,0
- Fps: -
- -
-
-
-
-
-
-
-
-
-
-
-
- + -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- diff --git a/apps/web-client/package.json b/apps/web-client/package.json index 5d68e6a..0cc4462 100644 --- a/apps/web-client/package.json +++ b/apps/web-client/package.json @@ -10,9 +10,12 @@ }, "dependencies": { "@craft/engine": "1.0.0", + "@tailwindcss/vite": "^4.1.7", "gl-matrix": "2.4.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^6.8.0", + "tailwindcss": "^4.1.7" }, "devDependencies": { "@craft/eslint-config-tylercraft": "^1.0.0", diff --git a/apps/web-client/public/app.css b/apps/web-client/public/app.css deleted file mode 100644 index 44f3d42..0000000 --- a/apps/web-client/public/app.css +++ /dev/null @@ -1,331 +0,0 @@ -@keyframes lift { - 0% { - box-shadow: 8px 8px 10px grey; - } - 100% { - box-shadow: 15px 15px 10px grey; - } -} - -@keyframes fade { - 0% { - visibility: visible; - opacity: 1; - } - 100% { - opacity: 0; - display: none; - visibility: hidden; - } -} - -html, -body { - margin: 0px; - padding: 0px; - overflow: hidden; - font-family: "Roboto", sans-serif; -} - -/* ======================== - HUD -=========================*/ -#hud { - --button-size: 50px; -} - -#hudCanvas { - position: absolute; - left: 0px; - top: 0px; - z-index: 10; - pointer-events: none; - visibility: hidden; -} - -#hud { - position: fixed; - left: 0px; - top: 0px; - width: 100%; - height: 100%; - visibility: hidden; -} - -#hud #crosshairs { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 30px; - height: 30px; -} - -#hud #crosshairs #verticalCrosshair { - position: absolute; - width: 10%; - height: 100%; - left: 45%; - background-color: red; -} - -#hud #crosshairs #horizontalCrosshair { - position: absolute; - height: 10%; - width: 100%; - top: 45%; - background-color: red; -} - -#hud #stats { - position: absolute; - color: red; - background-color: black; - padding: 3px; - opacity: 0.9; - font: 14px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -#hud #toolbelt { - position: absolute; - bottom: 10px; - height: 50px; - width: 500px; - left: 50%; - transform: translate(-50%, 0); - display: flex; - justify-content: space-evenly; - border: solid white 2px; -} - -#hud .toolbelt-item { - height: 42px; - width: 42px; - border: solid white 2px; - box-sizing: border-box; - margin: 3px; -} - -#hud .selected { - border: solid red 2px; -} - -#hud .toolbelt-item h2 { - color: white; - margin: 0px; -} - -#hud #useItemButton { - position: absolute; - background-color: blue; - right: 60px; - bottom: 30px; - width: var(--button-size); - height: var(--button-size); -} - -#hud #useItemButton2 { - position: absolute; - background-color: blue; - right: 10px; - bottom: 30px; - width: var(--button-size); - height: var(--button-size); -} - -#hud #healthBarOutline { - position: absolute; - width: 50%; - height: 30px; - bottom: 70px; - left: 25%; - border: white solid 2px; -} - -#hud #healthBar { - width: 100%; - height: 100%; - background-color: red; -} - -#hud #forwardButton { - position: absolute; - left: 30px; - bottom: 80px; - width: var(--button-size); - height: var(--button-size); - background-color: blue; -} - -#hud #jumpButton { - position: absolute; - background-color: blue; - bottom: 40px; - left: 30px; - width: var(--button-size); - height: var(--button-size); -} - -#hud #menuIcon { - position: absolute; - right: 5px; - top: 5px; - padding: 2px 5px; - border-radius: 5px; - background-color: white; - cursor: pointer; -} - -/* ======================== - Start Menu -=========================*/ - -#GamePickers { - display: flex; - flex-direction: column; -} - - -#startMenu { - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height: 100%; - display: flex; - align-items: center; - flex-direction: column; - overflow-y: auto; -} - -#startMenu.hidden { - display: none; -} - -#loadingScreen.shown { - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height: 100%; - - display: flex; - justify-content: center; - align-items: center; - font-family: "Indie Flower", cursive; - font-size: 3em; - text-align: center; -} - -#loadingScreen.hidden { - display: none; -} - -h1 { - font-size: 5em; - font-family: "Indie Flower", cursive; -} - -#subtitle { - font-size: 2em; - font-family: "Indie Flower", cursive; - margin-top: -40px; -} - -button { - border: none; - padding: 10px 100px; - margin-bottom: 30px; - font-size: 3em; - font-family: "Roboto", sans-serif; - cursor: pointer; - box-shadow: 8px 8px 10px grey; - border-radius: 10px; -} - -button:hover { - box-shadow: 15px 15px 10px grey; - animation: lift 0.1s linear; -} - -#backButton { - font-size: 6em; - position: absolute; - top: -30px; - cursor: pointer; - left: 0px; - display: none; -} - -#backButton.shown { - display: block; -} - -.fade { - visibility: hidden; - animation: fade 1s linear; -} - -#pickGameTypeScreen.shown { - display: block; -} - -#pickGameTypeScreen.hidden { - display: none; -} - -#pickWorldScreen.hidden { - display: none; -} - -#pickWorldScreen.shown { - display: flex; - flex-direction: column; -} - -#worldOptionsScreen.hidden { - display: none; -} - -#worldOptionsScreen.shown { - flex-direction: column; - justify-content: center; -} - -#configFormStartButton { - width: 100%; -} - - -.gameItem { - margin: 10px; -} - -#configForm .container { - margin-bottom: 10px; - border-radius: 10px; - padding: 10px; - background-color: #efefef; -} - -.form-row { - display: flex; - justify-content: space-between; - margin-bottom: 4px; -} - -.form-row input { - background-color: transparent; - border-top: none; - border-left: none; - border-right: none; - border-bottom: 1px black solid; - margin-left: 5px; - text-align: center; - width: 181px; -} - -.form-row label { - font-weight: 550; - font-family: "Roboto"; -} diff --git a/apps/web-client/src/App.tsx b/apps/web-client/src/App.tsx new file mode 100644 index 0000000..a36fe4a --- /dev/null +++ b/apps/web-client/src/App.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import HomePage from "./components/HomePage"; +import { ServerGameView } from "./components/ServerGameView"; +import { ServerHomePage } from "./components/ServerHomePage"; +import { ClientHomePage } from "./components/ClientHomePage"; +import { ClientGameView } from "./components/ClientGameView"; + +function App() { + return ( + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + ); +} + +export default App; diff --git a/apps/web-client/src/app.css b/apps/web-client/src/app.css new file mode 100644 index 0000000..1b2bb23 --- /dev/null +++ b/apps/web-client/src/app.css @@ -0,0 +1,5 @@ +@import "tailwindcss"; + +.toolbelt-item.selected { + border-color: red; +} diff --git a/apps/web-client/src/app.ts b/apps/web-client/src/app.ts deleted file mode 100644 index ca3699f..0000000 --- a/apps/web-client/src/app.ts +++ /dev/null @@ -1,411 +0,0 @@ -/** Entry point for the browser app - * Controls string UI and creating the game - */ -import * as Engine from "@craft/engine"; -console.log("Engine", Engine); -import { - camelCaseToNormalCase, - CONFIG, - Game, - IGameMetadata, -} from "@craft/engine"; -import { SocketHandler } from "./socket"; -import { renderWorldPicker } from "./world-picker"; -import { createRoot } from "react-dom/client"; -import { ClientDbGamesService } from "./services/sp-games-service"; -import { NetworkGamesService } from "./services/mp-games-service"; -import { BasicGScript } from "./game-scripts/basic-gscript"; - -export interface IExtendedWindow extends Window { - game?: Game; -} - -// Loading the engine -await Engine.WorldModule.load(); - -export const IS_MOBILE = /Mobi/.test(window.navigator.userAgent); -console.log("Is Mobile: ", IS_MOBILE); - -// helper functions -function showElement(e: HTMLElement) { - e.classList.remove("hidden"); - e.classList.add("shown"); -} - -function hideElement(e: HTMLElement) { - e.classList.add("hidden"); - e.classList.remove("shown"); -} - -function getElementByIdOrThrow(id: string): HTMLElement { - const e = document.getElementById(id); - if (!e) { - throw new Error(`Element with id ${id} not found`); - } - return e; -} - -// generate your unique id -// kind of bad to do this client side, but I can make it better later -const UID_KEY = "tylercraft-uid"; -if (!localStorage.getItem(UID_KEY)) { - localStorage.setItem(UID_KEY, Math.random() + ""); -} - -export function getMyUid() { - const uid = localStorage.getItem(UID_KEY); - if (!uid) throw new Error("UID not defined"); - return uid; -} - -// Get all of the elements -const ePlayLocalButton = getElementByIdOrThrow("playLocalButton"); -const ePlayOnlineButton = getElementByIdOrThrow("playOnlineButton"); -export const eStartMenu = getElementByIdOrThrow("startMenu"); -const eGameTypeScreen = getElementByIdOrThrow("pickGameTypeScreen"); -export const ePickWorldScreen = getElementByIdOrThrow("pickWorldScreen"); -const eBackButton = getElementByIdOrThrow("backButton"); -const eWorldOptionsScreen = getElementByIdOrThrow("worldOptionsScreen"); -const eConfigForm = getElementByIdOrThrow("configForm") as HTMLFormElement; -const eConfigFormExtra = getElementByIdOrThrow("configFormExtra"); -const eConfigFormStartButton = getElementByIdOrThrow( - "configFormStartButton" -) as HTMLButtonElement; -const eLoadingScreen = getElementByIdOrThrow("loadingScreen"); -const eLoadingScreenMsg = getElementByIdOrThrow("loadingScreenMsg"); - -const LoadingScreen = { - show: (msg: string) => { - showElement(eLoadingScreen); - eLoadingScreenMsg.innerHTML = msg; - }, - hide: () => { - hideElement(eLoadingScreen); - }, - fade: () => { - eLoadingScreen.classList.add("fade"); - }, -}; - -// Add listeners -ePlayLocalButton.addEventListener("click", showLocalWorldPicker); -ePlayOnlineButton.addEventListener("click", showOnlineWorldPicker); - -export const SocketInterface = new SocketHandler(); - -// Screens: - -// Start -// Choose Local World (#local) -// Create Local World (#local-new) -// Choose Server World (#server) -// Create Server World (#server-new) - -// select certain screen based on the location hash -console.log("Location hash", location.hash); -if (location.hash === "#local") { - showLocalWorldPicker(); -} else if (location.hash === "#online") { - showOnlineWorldPicker(); -} else if (location.hash === "#online-new") { - showOnlineNewWorldScreen(); -} else if (location.hash === "#local-new") { - showLocalNewWorldScreen(); -} - -export async function getLocalGamesService() { - const clientDb = await ClientDbGamesService.factory(); - return clientDb; -} - -async function getOnlineGamesService() { - const serverWorldModel = new NetworkGamesService(); - await SocketInterface.connect(() => { - console.error("Failed to connect to server"); - }); - return serverWorldModel; -} - -// Auto load a game if a URL query is present -async function loadGameFromUrl() { - const gameId = new URL(location.href).searchParams.get("worldId"); - - if (!gameId) { - console.log("No id found in url"); - return; - } - - hideElement(eStartMenu); - LoadingScreen.show("Pinpointing Location"); - - const findAndStartGame = async (gamesService: Engine.IGamesService) => { - const game = await gamesService.getGame(gameId); - if (game) { - await startGame(game); - return true; - } - return false; - }; - - console.log("Loading game", gameId); - - const clientWorldModel = await getLocalGamesService(); - if (await findAndStartGame(clientWorldModel)) { - return; - } - - LoadingScreen.show("Searching the Cloud"); - - const serverWorldModel = await getOnlineGamesService(); - if (await findAndStartGame(serverWorldModel)) { - return; - } - - console.log("Id not found"); - - LoadingScreen.show("Game not found 😱"); - - await new Promise((resolve) => setTimeout(resolve, 1000)); - - showElement(eStartMenu); - LoadingScreen.hide(); - - // remove id from url - const url = new URL(location.href); - url.searchParams.delete("worldId"); - history.replaceState(null, "", url.href); -} - -await loadGameFromUrl(); - -// Display Screen Functions -async function showLocalWorldPicker() { - const clientDb = await getLocalGamesService(); - showWorldPicker(clientDb, "local", "local-new", () => showLocalWorldPicker()); -} - -async function showOnlineWorldPicker() { - const serverWorldModel = await getOnlineGamesService(); - showWorldPicker(serverWorldModel, "online", "online-new", () => - showOnlineWorldPicker() - ); -} - -async function showLocalNewWorldScreen() { - hideElement(eGameTypeScreen); - const clientDb = await getLocalGamesService(); - showWorldOptionsScreen(clientDb, () => showLocalWorldPicker()); -} - -async function showOnlineNewWorldScreen() { - hideElement(eGameTypeScreen); - const clientDb = await getLocalGamesService(); - showWorldOptionsScreen(clientDb, () => showOnlineWorldPicker()); -} - -async function showWorldPicker( - gameManager: Engine.IGamesService, - currentHash: string, - nextHash: string, - onBack: () => void -) { - hideElement(eGameTypeScreen); - hideElement(eWorldOptionsScreen); - - // get all the saved worlds - const games = await gameManager.getAllGames(); - - const onGameSelect = async (gameMetaData: IGameMetadata) => { - location.hash = nextHash; - const game = await gameManager.getGame(gameMetaData.gameId); - if (!game) { - throw new Error("World wasn't found. Db must be effed up"); - } - - await startGame(game); - }; - - const onNewGame = () => { - console.log("Starting new game"); - showWorldOptionsScreen(gameManager, onBack); - }; - - const gamePickerHtml = renderWorldPicker({ - games, - onGameSelect, - onNewGame, - }); - - const root = createRoot(ePickWorldScreen); - root.render(gamePickerHtml); - - // Display the games now that they are populated - location.hash = currentHash; - showElement(ePickWorldScreen); - showElement(eBackButton); - - eBackButton.onclick = () => { - location.hash = ""; - hideElement(ePickWorldScreen); - hideElement(eBackButton); - showElement(eGameTypeScreen); - }; -} - -function createConfigHtmlObject( - obj: Record, - prefix: string -): string { - return Object.entries(obj).reduce( - (acc, config) => acc + createConfigHtml(config, prefix), - "" - ); -} - -function createConfigHtml( - [configKey, configValue]: [string, unknown], - prefix: string -): string { - const label = - camelCaseToNormalCase(prefix.replace(/,/g, " ")) + - camelCaseToNormalCase(configKey); - switch (typeof configValue) { - case "object": - return createConfigHtmlObject( - configValue as Record, - `${prefix + configKey + ","}` - ); - case "boolean": - return ` -
- - -
- `; - case "string": - return ` -
- - -
- `; - case "number": - return ` -
- - -
- `; - } - return ""; -} - -function showWorldOptionsScreen( - gameManager: Engine.IGamesService, - onBack: () => void -) { - showElement(eWorldOptionsScreen); - showElement(eBackButton); - hideElement(ePickWorldScreen); - eBackButton.onclick = onBack; - - // Goal: - // Make a way to extract all of the properties from the CONFIG and make - // an input for each one of them. When the input is changed, - // a temp config variable is changed and then saved to the game - - eConfigFormExtra.innerHTML = createConfigHtmlObject(CONFIG, ""); - - // When the game is started, update CONFIG with the the inputted values - eConfigFormStartButton.addEventListener("click", async () => { - const formData = new FormData(eConfigForm); - - const assignValueToConfig = ( - prefix: string, - obj: Record, - configKey: string, - configValue: unknown - ) => { - const newValue = formData.get(prefix + configKey); - switch (typeof configValue) { - case "number": - obj[configKey] = Number(newValue); - break; - case "boolean": - obj[configKey] = Boolean(newValue); - break; - case "string": - obj[configKey] = newValue; - break; - case "object": - assignValuesToConfigObject( - prefix + configKey + ",", - obj[configKey] as Record - ); - break; - } - }; - - const assignValuesToConfigObject = ( - prefix: string, - obj: Record - ) => { - Object.entries(obj).forEach(([configKey, configValue]) => - assignValueToConfig(prefix, obj, configKey, configValue) - ); - }; - - assignValuesToConfigObject("", CONFIG); - - const name = formData.get("name") as string; - - await createGame(gameManager, { config: CONFIG, name }); - }); -} - -async function createGame( - gameManager: Engine.IGamesService, - createGameOptions: Engine.ICreateGameOptions -) { - hideElement(eWorldOptionsScreen); - hideElement(eStartMenu); - - LoadingScreen.show("Painting the Sky"); - await Engine.WorldModule.load(); - - console.log("Creating Game | options=", createGameOptions); - - LoadingScreen.show("Forming clouds"); - const game = await gameManager.createGame(createGameOptions); - - await startGame(game); -} - -async function startGame(game: Engine.Game) { - hideElement(eWorldOptionsScreen); - hideElement(eStartMenu); - console.log("Starting Game", game); - - LoadingScreen.show("Painting the Sky"); - - console.log("Game Loaded, Starting game", game); - - (window as IExtendedWindow).game = game; - history.pushState("Game", "", `?worldId=${game.gameId}`); - - LoadingScreen.show("Building Mountains"); - - game.addGameScript(BasicGScript); - await game.setupScripts(); - game.startTimer(); - - console.log("Game Started"); - - LoadingScreen.fade(); - ePickWorldScreen.classList.add("fade"); - eStartMenu.classList.add("fade"); -} diff --git a/apps/web-client/src/cameras/entityCamera.ts b/apps/web-client/src/cameras/entityCamera.ts deleted file mode 100644 index f64a2d7..0000000 --- a/apps/web-client/src/cameras/entityCamera.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Vector3D, MovableEntity, CONFIG, Camera } from "@craft/engine"; - -export enum PlayerPerspective { - FirstPerson, - ThirdPersonBack, - ThirdPersonFront, -} - -export class EntityCamera extends Camera { - private perspective = PlayerPerspective.FirstPerson; - offset: Vector3D = Vector3D.zero; - rot: Vector3D; - - constructor(public entity: MovableEntity) { - super(); - this.rot = entity.rot.copy(); - } - - // cycles through player perspectives. Returns weather the player should be rendered or not - public togglePerspective(): boolean { - this.perspective = - this.perspective === PlayerPerspective.FirstPerson - ? PlayerPerspective.ThirdPersonBack - : this.perspective === PlayerPerspective.ThirdPersonBack - ? PlayerPerspective.ThirdPersonFront - : PlayerPerspective.FirstPerson; - - return this.perspective !== PlayerPerspective.FirstPerson; - } - - rotateBy(x: number, y: number) { - this.entity.rotate(new Vector3D([1, x, y])); - // set my rot as my entities rot - if (this.perspective === PlayerPerspective.ThirdPersonFront) { - this.rot = this.entity.rot.add(new Vector3D([0, Math.PI, 0])); - } else { - this.rot = this.entity.rot.copy(); - } - } - - get pos(): Vector3D { - let offset = Vector3D.zero; - - if (this.perspective === PlayerPerspective.ThirdPersonBack) { - offset = this.entity.rot - .add(new Vector3D([CONFIG.player.thirdPersonCamDist, 0, 0])) - .toCartesianCoords() - .multiply(new Vector3D([1, -1, 1])); - } else if (this.perspective === PlayerPerspective.ThirdPersonFront) { - this.rot = this.entity.rot.add(new Vector3D([0, Math.PI, 0])); - offset = this.entity.rot - .add(new Vector3D([CONFIG.player.thirdPersonCamDist, Math.PI, 0])) - .toCartesianCoords() - .multiply(new Vector3D([1, -1, 1])); - } else { - offset = this.offset; - } - - offset = offset.add( - new Vector3D([ - this.entity.dim[0] / 2, - this.entity.dim[1] * (9 / 10), - this.entity.dim[2] / 2, - ]) - ); - - return offset.add(this.entity.pos); - } - - set pos(_pos: Vector3D) { - /* NO-OP */ - } -} diff --git a/apps/web-client/src/components/ClientGameView.tsx b/apps/web-client/src/components/ClientGameView.tsx new file mode 100644 index 0000000..9eb32aa --- /dev/null +++ b/apps/web-client/src/components/ClientGameView.tsx @@ -0,0 +1,86 @@ +import React, { useState } from "react"; +import { run, create } from "../services/sp-games-service"; +import { RunningGameView } from "./RunningGameView"; +import { useNavigate, useParams } from "react-router-dom"; +import { CreateGameOptions } from "@craft/rust-world"; + +export function ClientGameView() { + const { gameId } = useParams<{ gameId: string }>(); + const navigate = useNavigate(); + const defaultOptions = CreateGameOptions.default(); + const [gameName, setGameName] = useState(defaultOptions.name); + const [seed, setSeed] = useState(defaultOptions.seed); + const [flatWorld, setFlatWorld] = useState(defaultOptions.flatWorld); + const [flatWorldHeight, setFlatWorldHeight] = useState( + defaultOptions.flatWorldHeight + ); + const [debugWorld, setDebugWorld] = useState(defaultOptions.debugWorld); + + async function createGame() { + const options = new CreateGameOptions( + gameName, + flatWorld, + flatWorldHeight, + debugWorld, + seed + ); + const id = await create(options); + navigate(`/client-game/${id}`); + } + + if (!gameId) { + return ( +
+ Create Game +
+ + setGameName(e.target.value)} + /> +
+
+ + setSeed(Number(e.target.value))} + /> +
+
+ + setFlatWorld(e.target.checked)} + /> +
+
+ + setFlatWorldHeight(Number(e.target.value))} + /> +
+
+ + setDebugWorld(e.target.checked)} + /> +
+ +
+ ); + } + + return ; +} diff --git a/apps/web-client/src/components/ClientHomePage.tsx b/apps/web-client/src/components/ClientHomePage.tsx new file mode 100644 index 0000000..600946f --- /dev/null +++ b/apps/web-client/src/components/ClientHomePage.tsx @@ -0,0 +1,51 @@ +import { IGameMetadata } from "@craft/engine"; +import React, { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { spGameService } from "../services/sp-games-service"; +import { OptionButton } from "./ui/Buttons"; + +export function ClientHomePage() { + const [games, setGames] = useState([]); + const [loading, setLoading] = useState(true); + const navigate = useNavigate(); + + const newGame = async () => { + navigate("/client-game"); + }; + + useEffect(() => { + spGameService.getAllGames().then((games) => { + setGames(games); + setLoading(false); + }); + }, []); + + if (loading) { + return
Loading...
; + } + + return ( +
+
navigate("/")} + > + ⬅ +
+

Local Games

+
+ {games.length > 0 && + games.map((game) => ( + navigate(`/client-game/${game.gameId}`)} + > + {game.name || game.gameId} + + ))} + {games.length === 0 &&

No games available

} + Create Game +
+
+ ); +} diff --git a/apps/web-client/src/components/GameConfigMenu.tsx b/apps/web-client/src/components/GameConfigMenu.tsx new file mode 100644 index 0000000..742a982 --- /dev/null +++ b/apps/web-client/src/components/GameConfigMenu.tsx @@ -0,0 +1,436 @@ +import React, { useEffect, useState } from "react"; +import { BooleanInput, NumberInput, TextInput } from "./ui/Inputs"; +import { RunningGame } from "../services/sp-games-service"; +import { useNavigate } from "react-router-dom"; +import { TeleportAction } from "@craft/rust-world"; + +interface GameConfigMenuProps { + runningGame: RunningGame; + isOpen: boolean; + onClose: () => void; +} + +interface ScriptConfig { + [key: string]: any; +} + +interface ChunkFetcherConfig { + type: string; + json: { + [key: string]: any; + }; +} + +type ActiveTab = "Chunk Fetcher" | "Game Config" | "Player Actions" | string; + +function MenuLabel({ children }: { children: React.ReactNode }) { + return {children}; +} + +export function GameConfigMenu({ + runningGame, + isOpen, + onClose, +}: GameConfigMenuProps) { + const game = runningGame.game; + const [scriptNames, setScriptNames] = useState([]); + const [scriptConfigs, setScriptConfigs] = useState<{ + [scriptName: string]: ScriptConfig; + }>({}); + const [chunkFetcherConfig, setChunkFetcherConfig] = + useState(game.serializeChunkFetcher()); + const [activeTab, setActiveTab] = useState("Game Config"); + const [gameName, setGameName] = useState(game.name); + const [tpX, setTpX] = useState(0); + const [tpY, setTpY] = useState(0); + const [tpZ, setTpZ] = useState(0); + const navigate = useNavigate(); + + // Load current player position when Player Actions tab is opened + useEffect(() => { + if (isOpen && activeTab === "Player Actions") { + const player = game.getEntityAsPlayer(runningGame.playerId); + if (player) { + const pos = player.pos; + setTpX(Math.round(pos.x * 100) / 100); + setTpY(Math.round(pos.y * 100) / 100); + setTpZ(Math.round(pos.z * 100) / 100); + } + } + }, [isOpen, activeTab]); + + useEffect(() => { + if (isOpen && runningGame) { + // Get all script names + const names = game.getScriptNames(); + setScriptNames(names); + + // Get configs for all scripts + const configs: { [scriptName: string]: ScriptConfig } = {}; + names.forEach((name) => { + try { + const config: Map = game.getScriptConfig(name); + console.log("Config", name, config); + if (config) { + if (config instanceof Map) { + configs[name] = Object.fromEntries(config); + } else { + configs[name] = config; + } + } + } catch (error) { + console.warn(`Failed to get config for script ${name}:`, error); + configs[name] = {}; + } + }); + + console.log("Configs", configs); + + setScriptConfigs(configs); + + // Get chunk fetcher config + try { + const chunkConfig: ChunkFetcherConfig = game.serializeChunkFetcher(); + console.log("Chunk Fetcher Config", chunkConfig); + if (chunkConfig) { + if (chunkConfig.json instanceof Map) { + chunkConfig.json = Object.fromEntries(chunkConfig.json); + } + setChunkFetcherConfig(chunkConfig); + } + } catch (error) { + console.warn("Failed to get chunk fetcher config:", error); + setChunkFetcherConfig({ type: "", json: {} }); + } + } + }, [isOpen, runningGame, activeTab]); + + const handleConfigChange = (scriptName: string, key: string, value: any) => { + const updatedConfigs = { + ...scriptConfigs, + [scriptName]: { + ...scriptConfigs[scriptName], + [key]: value, + }, + }; + setScriptConfigs(updatedConfigs); + + // Update the game script config + try { + game.setScriptConfig(scriptName, updatedConfigs[scriptName]); + } catch (error) { + console.error(`Failed to update config for script ${scriptName}:`, error); + } + }; + + const handleChunkFetcherConfigChange = (key: string, value: any) => { + const updatedConfig = { + ...chunkFetcherConfig, + json: { + ...chunkFetcherConfig.json, + [key]: value, + }, + }; + setChunkFetcherConfig(updatedConfig); + + // Update the game chunk fetcher config + try { + game.setChunkFetcherConfig(updatedConfig); + } catch (error) { + console.error("Failed to update chunk fetcher config:", error); + } + }; + + const handleGameNameChange = (value: string) => { + game.name = value; + setGameName(value); + }; + + const handleTeleport = () => { + const action = TeleportAction.make_wasm(runningGame.playerId, tpX, tpY, tpZ); + runningGame.onAction(action); + }; + + const handleSaveGame = () => { + runningGame.save(); + }; + + const handleExit = () => { + runningGame.cleanup(); + navigate("/client"); + }; + + const renderConfigValue = (scriptName: string, key: string, value: any) => { + console.log("RenderConfigValue", scriptName, key, value); + const handleChange = (newValue: any) => { + handleConfigChange(scriptName, key, newValue); + }; + + if (typeof value === "boolean") { + return ( +
+ {key}: + handleChange(e)} /> +
+ ); + } else if (typeof value === "number") { + return ( +
+ {key}: + handleChange(e)} + /> +
+ ); + } else if (typeof value === "string") { + return ( +
+ {key}: + handleChange(e)} /> +
+ ); + } else { + return ( +
+ {key}: + + {JSON.stringify(value)} + +
+ ); + } + }; + + const renderChunkFetcherConfigValue = (key: string, value: any) => { + console.log("RenderChunkFetcherConfigValue", key, value); + const handleChange = (newValue: any) => { + handleChunkFetcherConfigChange(key, newValue); + }; + + if (typeof value === "boolean") { + return ( +
+ {key}: + handleChange(e)} /> +
+ ); + } else if (typeof value === "number") { + return ( +
+ {key}: + handleChange(e)} + /> +
+ ); + } else if (typeof value === "string") { + return ( +
+ {key}: + handleChange(e)} /> +
+ ); + } else { + return ( +
+ {key}: + + {JSON.stringify(value)} + +
+ ); + } + }; + + if (!isOpen) return null; + + const activeConfig = scriptConfigs[activeTab]; + + console.log("ActiveConfig", activeConfig, scriptConfigs, activeTab); + + return ( +
+
+
+

Menu

+
+ + + +
+
+ +
+ {scriptNames.length === 0 && + chunkFetcherConfig.json && + Object.keys(chunkFetcherConfig.json).length === 0 ? ( +
+ No configuration options found +
+ ) : ( + <> +
+ + {/* Chunk Fetcher Tab */} + + + {/* Player Actions Tab */} + + + {/* Script Tabs */} + {scriptNames.map((name) => ( + + ))} +
+ +
+ {activeTab === "Chunk Fetcher" ? ( +
+

+ Chunk Fetcher Configuration +

+ {Object.entries(chunkFetcherConfig.json).map( + ([key, value]) => ( +
+ {renderChunkFetcherConfigValue(key, value)} +
+ ) + )} + {Object.keys(chunkFetcherConfig).length === 0 && ( +
+ No configuration options available +
+ )} +
+ ) : activeTab === "Player Actions" ? ( +
+

+ Player Actions +

+ +

Teleport

+
+ X: + setTpX(v)} + /> +
+
+ Y: + setTpY(v)} + /> +
+
+ Z: + setTpZ(v)} + /> +
+ +
+ ) : activeTab === "Game Config" ? ( +
+

+ Game Config +

+ + Game Name: + handleGameNameChange(e)} + /> +
+ ) : activeTab && scriptConfigs[activeTab] ? ( +
+

+ {activeTab} Configuration +

+ {Object.entries(scriptConfigs[activeTab]).map( + ([key, value]) => ( +
+ {renderConfigValue(activeTab, key, value)} +
+ ) + )} + {Object.keys(scriptConfigs[activeTab]).length === 0 && ( +
+ No configuration options available +
+ )} +
+ ) : null} +
+ + )} +
+
+
+ ); +} diff --git a/apps/web-client/src/components/HomePage.tsx b/apps/web-client/src/components/HomePage.tsx new file mode 100644 index 0000000..09d7d0f --- /dev/null +++ b/apps/web-client/src/components/HomePage.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import { useNavigate } from "react-router-dom"; +import { TitleButton } from "./ui/Buttons"; + +function HomePage() { + const navigate = useNavigate(); + + return ( +
+

+ TylerCraft +

+

+ A 3D sandbox game by Tyler Tracy +

+
+ navigate("/client")}> + Play Local + + navigate("/server")}> + Play Online + +
+
+ ); +} + +export default HomePage; diff --git a/apps/web-client/src/components/RunningGameView.tsx b/apps/web-client/src/components/RunningGameView.tsx new file mode 100644 index 0000000..7de7403 --- /dev/null +++ b/apps/web-client/src/components/RunningGameView.tsx @@ -0,0 +1,112 @@ +import React, { useEffect, useRef, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { RunGameError, RunningGame } from "../services/running-game"; +import { GameConfigMenu } from "./GameConfigMenu"; +import { GameRendererGameScript } from "../renders/game-renderer"; +import { MenuButton } from "./ui/Buttons"; + +GameRendererGameScript.register(); + +export function RunningGameView(props: { + runFn: ( + uiMessage: (message: string) => void, + gameId: string + ) => Promise; + backUrl: string; + gameId: string; +}) { + const { runFn, backUrl, gameId } = props; + const [isLoading, setIsLoading] = useState(true); + const [showConfigMenu, setShowConfigMenu] = useState(false); + const [gameInstance, setGameInstance] = useState(null); + const [error, setError] = useState(null); + const navigate = useNavigate(); + const loadingMessageRef = useRef(null); + + async function startGame(gameId: string) { + console.log("Starting game", gameId); + const updateLoadingMessage = (message: string) => { + console.log("Updating loading message", message); + if (loadingMessageRef.current) { + console.log("Updating loading message", message); + loadingMessageRef.current.innerHTML = message; + } + }; + + try { + const runningGame = await runFn(updateLoadingMessage, gameId); + if ("game" in runningGame) { + setGameInstance(runningGame); + } else { + setError(runningGame.error); + } + } catch (err) { + console.error("Error starting game", err); + setError(err as string); + } + setIsLoading(false); + } + + useEffect(() => { + startGame(gameId); + }, []); + + useEffect(() => { + if (!gameInstance) { + return; + } + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") { + setShowConfigMenu(!showConfigMenu); + } + }; + + document.addEventListener("keydown", handleKeyDown); + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, [showConfigMenu, gameInstance]); + + if (isLoading) { + return ( +
+ Loading +
+ {" "} +
+
+ ); + } + + if (error) { + return ( +
+ {" "} + There was an error, Check the console for more details:{" "} + {JSON.stringify(error)}
+ navigate(backUrl)}> + Back To Client Games + +
+ ); + } + + return ( +
+
+ setShowConfigMenu(true)}> + Game Config (ESC) + +
+ + {gameInstance && ( + setShowConfigMenu(false)} + /> + )} +
+ ); +} diff --git a/apps/web-client/src/components/ServerGameView.tsx b/apps/web-client/src/components/ServerGameView.tsx new file mode 100644 index 0000000..2e49d86 --- /dev/null +++ b/apps/web-client/src/components/ServerGameView.tsx @@ -0,0 +1,87 @@ +import React, { useState } from "react"; +import { run, create } from "../services/mp-games-service"; +import { RunningGameView } from "./RunningGameView"; +import { useNavigate, useParams } from "react-router-dom"; +import { CreateGameOptions } from "@craft/rust-world"; + +export function ServerGameView() { + const { gameId } = useParams<{ gameId: string }>(); + const navigate = useNavigate(); + const defaultOptions = CreateGameOptions.default(); + const [gameName, setGameName] = useState(defaultOptions.name); + const [seed, setSeed] = useState(defaultOptions.seed); + const [flatWorld, setFlatWorld] = useState(defaultOptions.flatWorld); + const [flatWorldHeight, setFlatWorldHeight] = useState( + defaultOptions.flatWorldHeight + ); + const [debugWorld, setDebugWorld] = useState(defaultOptions.debugWorld); + + async function createGame() { + const id = await create( + new CreateGameOptions( + gameName, + flatWorld, + flatWorldHeight, + debugWorld, + seed + ) + ); + navigate(`/server-game/${id}`); + } + + if (!gameId) { + return ( +
+ Create Game +
+ + setGameName(e.target.value)} + /> +
+
+ + setSeed(Number(e.target.value))} + /> +
+
+ + setFlatWorld(e.target.checked)} + /> +
+
+ + setFlatWorldHeight(Number(e.target.value))} + /> +
+
+ + setDebugWorld(e.target.checked)} + /> +
+ +
+ ); + } + + return ; +} diff --git a/apps/web-client/src/components/ServerHomePage.tsx b/apps/web-client/src/components/ServerHomePage.tsx new file mode 100644 index 0000000..c112b2e --- /dev/null +++ b/apps/web-client/src/components/ServerHomePage.tsx @@ -0,0 +1,70 @@ +import { IServerGameMetadata } from "@craft/engine"; +import React, { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { getAllGames } from "../services/mp-games-service"; +import { OptionButton } from "./ui/Buttons"; + +export function ServerHomePage() { + const [games, setGames] = useState([]); + const [loading, setLoading] = useState(true); + const navigate = useNavigate(); + + const createGameWrapper = async () => { + navigate("/server-game"); + }; + + useEffect(() => { + getAllGames().then((games) => { + setGames(games); + setLoading(false); + }); + }, []); + + if (loading) { + return
Loading...
; + } + + console.log(games); + + return ( +
+ navigate("/")} + > + ⬅ + +

+ Server Games +

+
+ { + createGameWrapper(); + }} + > + Create Game + +
+
+

+ Existing Games +

+ {games.length > 0 ? ( +
+ {games.map((game) => ( + navigate(`/server-game/${game.gameId}`)} + > + {game.name || game.gameId} + + ))} +
+ ) : ( +

No games available

+ )} +
+
+ ); +} diff --git a/apps/web-client/src/components/ui/Buttons.tsx b/apps/web-client/src/components/ui/Buttons.tsx new file mode 100644 index 0000000..03c5296 --- /dev/null +++ b/apps/web-client/src/components/ui/Buttons.tsx @@ -0,0 +1,36 @@ +import React from "react"; + +type ButtonProps = React.ButtonHTMLAttributes & { + className?: string; +}; + +const base = + "inline-flex items-center justify-center rounded-xl bg-white text-black shadow-md hover:shadow-xl transition-shadow duration-150 ease-out cursor-pointer border-0"; + +export function TitleButton({ className = "", ...props }: ButtonProps) { + return ( + - - - - ); - - const gameScriptSections = game.getScriptActions().map((s, i) => { - const actions = s.actions; - - return ( - openSection === "script-" + i && ( -
- {actions && - Object.keys(actions).map((name) => { - return ; - })} - - {s.config &&
{JSON.stringify(s.config, null, 2)}
} -
- ) - ); - }); - - const gameScriptButtons = game.getScriptActions().map((_s, i) => { - return ( - setOpenSection("script-" + i)} key={i}> - {"GameScript " + (i + 1)} - - ); - }); - - return ( - <> - - - {isOpen && ( -
-
- setOpenSection("main")}> - Main Menu - - setOpenSection("about")}> - About - - setOpenSection("config")}> - Config - - - {gameScriptButtons} -
- -
- {openSection === "main" && mainSection} - {openSection === "about" && } - {openSection === "config" && } - {gameScriptSections} -
-
- )} - - ); -}; - -const ConfigSection = (props: { game: Game }) => { - return
{JSON.stringify(props.game.config, null, 2)}
; -}; - -const AboutSection = () => { - return ( -
-

Made by Tyler Tracy

-
- ); -}; - -// export const renderGameMenu = (game: Game) => { -// const container = getEleOrError("menuContainer"); -// -// ReactDOM.render(, container); -// }; diff --git a/apps/web-client/src/game-scripts/hudRender.ts b/apps/web-client/src/renders/hud-renderer.ts similarity index 61% rename from apps/web-client/src/game-scripts/hudRender.ts rename to apps/web-client/src/renders/hud-renderer.ts index b659202..25b8e62 100644 --- a/apps/web-client/src/game-scripts/hudRender.ts +++ b/apps/web-client/src/renders/hud-renderer.ts @@ -1,16 +1,19 @@ -import { Game } from "@craft/engine"; -import TextureMapper from "../textureMapper"; -import { IS_MOBILE } from "../app"; -import { CanvasGameScript } from "../game-scripts/canvas-gscript"; -import { getEleOrError, hideElement } from "../utils"; -import { GameScript } from "@craft/engine/game-script"; -import { BasicGScript } from "./basic-gscript"; -import { GameMenu } from "../renders/gameMenuRender"; -import React from "react"; -import ReactDOM from "react-dom"; +import { GameScript } from "@craft/engine"; +import { GameRenderer } from "./game-renderer"; +import { getEleOrError, hideElement, IS_MOBILE } from "../utils"; +import { Game, Item, Player } from "@craft/rust-world"; +import TextureMapper from "../services/texture-mapping-service"; export class HudGScript extends GameScript { - name = "hud"; + name = "hud-renderer"; + + public config = { + enabled: true, + showStats: true, + showBelt: true, + showHealthBar: true, + opacity: 1.0, + }; textureImg: HTMLImageElement; private eHealthBar = getEleOrError("healthBar"); @@ -32,28 +35,19 @@ export class HudGScript extends GameScript { constructor( game: Game, - private basicGScript: BasicGScript, - private canvasGScript: CanvasGameScript + private gameRenderer: GameRenderer, + private mainPlayerUid: number ) { super(game); - // Show the things! - ReactDOM.render( - React.createElement(GameMenu, { game: game }), - this.eMenuContainer - ); - this.eHud.style.visibility = "visible"; this.textureImg = document.createElement("img"); - this.textureImg.src = "./img/texture_map.png"; + this.textureImg.src = "/img/texture_map.png"; + this.textureImg.style.display = "none"; document.body.appendChild(this.textureImg); - const getCanvasDimensions = () => { - this.eHudCanvas.height = window.innerHeight; - this.eHudCanvas.width = window.innerWidth; - }; - window.addEventListener("resize", getCanvasDimensions); + window.addEventListener("resize", this.updateCanvasDimensionsBound); const hudContext = this.eHudCanvas.getContext("2d"); if (!hudContext) { @@ -66,10 +60,22 @@ export class HudGScript extends GameScript { } this.textureImg.onload = () => { - this.drawBelt(); + // this.drawBelt(); }; } + cleanup() { + console.log("HudGScript: Cleaning up"); + this.eHud.style.visibility = "hidden"; + window.removeEventListener("resize", this.updateCanvasDimensionsBound); + } + + private updateCanvasDimensionsBound = this.updateCanvasDimensions.bind(this); + private updateCanvasDimensions() { + this.eHudCanvas.height = window.innerHeight; + this.eHudCanvas.width = window.innerWidth; + } + private getScreenDim(): [sw: number, sh: number] { return [window.innerWidth, window.innerHeight]; } @@ -93,16 +99,26 @@ export class HudGScript extends GameScript { } private lastStats = ""; - drawStats() { - const cameraPos = this.basicGScript.mainPlayer.pos.data - .map((d) => d.toFixed(2)) - .join(","); - const numChunks = this.game.world.getLoadedChunkIds().length; + drawStats(player: Player) { + const cameraPos = + "X: " + + player.pos.x.toFixed(2) + + ", Y: " + + player.pos.y.toFixed(2) + + ", Z: " + + player.pos.z.toFixed(2); + + const cameraRot = + "Theta: " + + player.rot.theta.toFixed(2) + + ", Phi: " + + player.rot.phi.toFixed(2); + // const numChunks = this.game.world.getLoadedChunkIds().length; const statsString = ` playerPos: ${cameraPos}
- fps: ${this.canvasGScript.frameRate.toFixed(0)}
- numChunks: ${numChunks} + playerRot: ${cameraRot}
+ fps: ${this.gameRenderer.frameRate.toFixed(0)}
`; if (this.lastStats !== statsString) { @@ -118,21 +134,32 @@ export class HudGScript extends GameScript { } update(_delta: number): void { + const player = this.game.getEntityAsPlayer(this.mainPlayerUid); + if (!player) { + console.log("HudGScript: Player not found", this.mainPlayerUid); + return; + } + this.clearScreen(); - this.drawStats(); + this.drawStats(player); - if (this.lastSelected !== this.basicGScript.mainPlayer.belt.selectedIndex) { - this.drawBelt(); - this.lastSelected = this.basicGScript.mainPlayer.belt.selectedIndex; - } + this.drawBelt(player); - this.drawHealthBar(); + this.drawHealthBar(player); } - drawBelt() { + drawBelt(player: Player) { + const belt = player.belt; + + if (belt.selected_item === this.lastSelected) { + return; + } + + this.lastSelected = belt.selected_item; + this.eToolbeltItems.forEach((item, index) => { - if (index === this.basicGScript.mainPlayer.belt.selectedIndex) { + if (index === belt.selected_item) { item.classList.add("selected"); } else { item.classList.remove("selected"); @@ -141,15 +168,9 @@ export class HudGScript extends GameScript { const itemDim = this.eToolbeltItems[0].clientHeight; - const belt = this.basicGScript.mainPlayer.belt; - - if (!belt) { - return; - } - // draw the icons - for (let i = 0; i < belt.length; i++) { - const item = belt.getItem(i); + for (let i = 0; i < belt.get_num_items(); i++) { + const item: Item = belt.get_item_js(i); if (!item) { continue; } @@ -187,10 +208,9 @@ export class HudGScript extends GameScript { } } - drawHealthBar() { - if (!this.basicGScript.mainPlayer) return; - const { current, max } = this.basicGScript.mainPlayer.health; - const healthPercent = current / max; + drawHealthBar(player: Player) { + const { health, max_health } = player.health; + const healthPercent = health / max_health; this.eHealthBar.style.width = `${healthPercent * 100}%`; } @@ -200,4 +220,9 @@ export class HudGScript extends GameScript { hideElement(this.eUseItemButton); hideElement(this.eUseItemButton2); } + + setConfig(config: typeof this.config): void { + this.config = { ...this.config, ...config }; + console.log("HudGScript config updated:", this.config); + } } diff --git a/apps/web-client/src/renders/imageRender.ts b/apps/web-client/src/renders/image-render.ts similarity index 94% rename from apps/web-client/src/renders/imageRender.ts rename to apps/web-client/src/renders/image-render.ts index d4fec7a..9d56528 100644 --- a/apps/web-client/src/renders/imageRender.ts +++ b/apps/web-client/src/renders/image-render.ts @@ -29,7 +29,7 @@ export class ImageReneCanvasderer extends Renderer { render(camera: Camera): void { this.setActiveTexture( - this.webGlGScript.getGalleryTexture(this.galleryIndex) + this.gameRenderer.getGalleryTexture(this.galleryIndex) ); this.renderObject(this.pos.data as IDim, camera); } diff --git a/apps/web-client/src/renders/playerRender.ts b/apps/web-client/src/renders/player-render.ts similarity index 65% rename from apps/web-client/src/renders/playerRender.ts rename to apps/web-client/src/renders/player-render.ts index 896b2b5..c6268c3 100644 --- a/apps/web-client/src/renders/playerRender.ts +++ b/apps/web-client/src/renders/player-render.ts @@ -1,24 +1,60 @@ -import { Player, Camera, Vector3D, IDim } from "@craft/engine"; +import { Camera, Vector3D } from "@craft/engine"; import { RenderData, Renderer } from "./renderer"; import ShapeBuilder from "../services/shape-builder"; -import TextureMapper from "../textureMapper"; -import { WebGlGScript } from "../game-scripts/webgl-gscript"; +import TextureMapper from "../services/texture-mapping-service"; +import { Game, Player } from "@craft/rust-world"; +import { GameRenderer } from "./game-renderer"; + +class PlayerRenderWrapper { + constructor(private player: Player) {} + + get pos() { + return this.player.pos; + } + + get distanceMoved() { + return 0; + } + + get dim() { + return new Vector3D([1, 1, 1]); + } + + get rot() { + return this.player.rot; + } +} export class PlayerRenderer extends Renderer { private renderData = new RenderData(); constructor( - webGlGScript: WebGlGScript, - - public player: Player + private game: Game, + protected gameRenderer: GameRenderer, + public entityId: number ) { - super(webGlGScript); - this.setActiveTexture(this.webGlGScript.textureAtlas); + super(gameRenderer); + this.setActiveTexture(this.gameRenderer.textureAtlas); } render(camera: Camera) { - this.calculateBuffers(); - this.renderObject(this.player.pos.data as IDim, camera); + const player = this.game.getEntityAsPlayer(this.entityId); + // console.log( + // "Rendering player with id", + // this.entityId, + // player?.pos.x, + // player?.pos.y, + // player?.pos.z + // ); + if (!player) { + throw new Error("Player with id " + this.entityId + " not found"); + } + const player_render_wrapper = new PlayerRenderWrapper(player); + this.calculateBuffers(player_render_wrapper); + this.renderObject( + new Vector3D([player.pos.x, player.pos.y, player.pos.z]), + camera + ); } static handSize = new Vector3D([0.2, 0.2, 0.2]); @@ -30,12 +66,11 @@ export class PlayerRenderer extends Renderer { static headSize = new Vector3D([0.6, 0.6, 0.6]); static halfHeadSize = PlayerRenderer.headSize.scalarMultiply(0.5); - drawHead() { - const theta = this.player.rot.get(1); - const phi = -this.player.rot.get(2) + Math.PI / 2; - const rightLegRot = Math.sin(this.player.distanceMoved); - const playerDimVec = new Vector3D(this.player.dim); - const halfPlayerSize = playerDimVec.scalarMultiply(0.5); + drawHead(player: PlayerRenderWrapper) { + const theta = player.rot.theta; + const phi = -player.rot.phi + Math.PI / 2; + const rightLegRot = Math.sin(0); + const halfPlayerSize = player.dim.scalarMultiply(0.5); const headPos = halfPlayerSize.add(new Vector3D([0, 0.9, 0])); ShapeBuilder.buildBox((edge) => { return edge @@ -47,7 +82,7 @@ export class PlayerRenderer extends Renderer { }, this.renderData); } - private calculateBuffers() { + private calculateBuffers(player: PlayerRenderWrapper) { this.renderData.clear(); const { renderData } = this; @@ -60,15 +95,14 @@ export class PlayerRenderer extends Renderer { textureCords, }); - const theta = this.player.rot.get(1); + const theta = player.rot.theta; // const phi = -this.player.rot.get(2) + Math.PI / 2; - const playerDimVec = new Vector3D(this.player.dim); const armSize = new Vector3D([0.3, 0.8, 0.3]); const bodySize = new Vector3D([0.4, 0.8, 0.8]); const legSize = new Vector3D([0.4, 0.7, 0.4]); - const halfPlayerSize = playerDimVec.scalarMultiply(0.5); + const halfPlayerSize = player.dim.scalarMultiply(0.5); const bodyOrigin = bodySize.scalarMultiply(0.5); const armOrigin = armSize.multiply(new Vector3D([0.5, 1, 0.5])); const legOrigin = legSize.multiply(new Vector3D([0.5, 1, 0.5])); @@ -87,13 +121,13 @@ export class PlayerRenderer extends Renderer { new Vector3D([0, -0.2, -0.2]).rotateY(theta) ); - const rightArmRot = Math.sin(this.player.distanceMoved); - const leftArmRot = Math.sin(this.player.distanceMoved + Math.PI); - const rightLegRot = Math.sin(this.player.distanceMoved); - const leftLegRot = Math.sin(this.player.distanceMoved + Math.PI); + const rightArmRot = Math.sin(player.distanceMoved); + const leftArmRot = Math.sin(player.distanceMoved + Math.PI); + const rightLegRot = Math.sin(player.distanceMoved); + const leftLegRot = Math.sin(player.distanceMoved + Math.PI); // draw head - this.drawHead(); + this.drawHead(player); // draw body ShapeBuilder.buildBox((edge) => { diff --git a/apps/web-client/src/renders/renderer.ts b/apps/web-client/src/renders/renderer.ts index c2aa925..891b0d6 100644 --- a/apps/web-client/src/renders/renderer.ts +++ b/apps/web-client/src/renders/renderer.ts @@ -1,6 +1,6 @@ -import { Camera, arraySub, IDim } from "@craft/engine"; +import { Camera, Vector3D } from "@craft/engine"; import { mat4, vec3 } from "gl-matrix"; -import { WebGlGScript } from "../game-scripts/webgl-gscript"; +import { GameRenderer } from "./game-renderer"; interface IRenderData { positions: number[]; @@ -50,10 +50,10 @@ export abstract class Renderer { amount = 0; transAmount = 0; - constructor(protected webGlGScript: WebGlGScript) {} + constructor(protected gameRenderer: GameRenderer) {} protected setBuffers(renData: IRenderData, transRenData?: IRenderData) { - const gl = this.webGlGScript.gl; + const gl = this.gameRenderer.gl; this.amount = renData.indices.length; @@ -120,8 +120,8 @@ export abstract class Renderer { // Tell WebGL how to pull out the positions from the position // buffer into the vertexPosition attribute. private bindCube(trans: boolean) { - const programInfo = this.webGlGScript.program; - const gl = this.webGlGScript.gl; + const programInfo = this.gameRenderer.program; + const gl = this.gameRenderer.gl; const posBuffer = trans ? this.transPosBuffer : this.posBuffer; const indexBuffer = trans ? this.transIndexBuffer : this.indexBuffer; @@ -146,8 +146,8 @@ export abstract class Renderer { // tell webgl how to pull out the texture coordinates from buffer private bindTexture(trans: boolean) { - const programInfo = this.webGlGScript.program; - const gl = this.webGlGScript.gl; + const programInfo = this.gameRenderer.program; + const gl = this.gameRenderer.gl; const textureBuffer = trans ? this.transTextureBuffer : this.textureBuffer; @@ -169,9 +169,9 @@ export abstract class Renderer { abstract render(camera: Camera): void; - renderXrObject(pos: number[], camera: Camera, trans?: boolean) { + renderXrObject(pos: Vector3D, camera: Camera, trans?: boolean) { const { currentXRFrame, xrRefSpace, gl, program, webXrSession } = - this.webGlGScript; + this.gameRenderer; if (!currentXRFrame || !xrRefSpace || !webXrSession) { return; } @@ -202,11 +202,13 @@ export abstract class Renderer { view.transform.inverse.matrix as mat4 ); + const move_pos = pos.sub(camera.pos).data; + // Now move the drawing position to where we want to start drawing the square. mat4.translate( modelViewMatrix, // destination matrix modelViewMatrix, // matrix to translate - new Float32Array(arraySub(pos, camera.pos.data)) as vec3 + new Float32Array(move_pos) as vec3 ); gl.uniformMatrix4fv( @@ -235,34 +237,33 @@ export abstract class Renderer { } } - renderObject(pos: IDim, camera: Camera, trans?: boolean) { - if (this.webGlGScript.currentXRFrame) { + renderObject(pos: Vector3D, camera: Camera, trans?: boolean) { + if (this.gameRenderer.currentXRFrame) { return this.renderXrObject(pos, camera, trans); } - const gl = this.webGlGScript.gl; - const programInfo = this.webGlGScript.program; + const gl = this.gameRenderer.gl; + const programInfo = this.gameRenderer.program; // Set the drawing position to the "identity" point, which is // the center of the scene. + + const theta = Math.PI - camera.rot.get(2); + const phi = camera.rot.get(1); const modelViewMatrix = mat4.create(); - mat4.rotate( - modelViewMatrix, - modelViewMatrix, - camera.rot.get(2) - Math.PI / 2, - [1, 0, 0] - ); - mat4.rotate( - modelViewMatrix, - modelViewMatrix, - camera.rot.get(1) - Math.PI / 2, - [0, 1, 0] - ); + + // Flip the image across the Y-axis by scaling X by -1 + mat4.scale(modelViewMatrix, modelViewMatrix, [-1, 1, 1]); + + mat4.rotate(modelViewMatrix, modelViewMatrix, phi, [1, 0, 0]); + mat4.rotate(modelViewMatrix, modelViewMatrix, theta, [0, 1, 0]); + + const move_pos = pos.sub(camera.pos).data; // Now move the drawing position to where we want to start drawing the square. mat4.translate( modelViewMatrix, // destination matrix modelViewMatrix, // matrix to translate - new Float32Array(arraySub(pos, camera.pos.data)) as vec3 + new Float32Array(move_pos) as vec3 ); this.bindCube(trans || false); diff --git a/apps/web-client/src/renders/sphereRender.ts b/apps/web-client/src/renders/sphere-render.ts similarity index 83% rename from apps/web-client/src/renders/sphereRender.ts rename to apps/web-client/src/renders/sphere-render.ts index 4786ffc..1ca425b 100644 --- a/apps/web-client/src/renders/sphereRender.ts +++ b/apps/web-client/src/renders/sphere-render.ts @@ -1,20 +1,38 @@ -import { WebGlGScript } from "../game-scripts/webgl-gscript"; +import { GameRenderer } from "./game-renderer"; import { RenderData, Renderer } from "./renderer"; -import { Camera, Entity, IDim } from "@craft/engine"; +import { Camera, Vector3D } from "@craft/engine"; +import { Game } from "@craft/rust-world"; export class SphereRenderer extends Renderer { radius = 1; - constructor(webGlGScript: WebGlGScript, public entity: Entity) { - super(webGlGScript); + constructor( + public game: Game, + protected gameRenderer: GameRenderer, + public entityId: number + ) { + super(gameRenderer); - this.radius = entity.dim[0]; + const fireball = game.entities.get_entity_as_fireball(entityId); + if (!fireball) { + throw new Error("Fireball not found"); + } + + this.radius = fireball.dim.x; this.setup(); } render(camera: Camera) { - this.renderObject(this.entity.pos.data as IDim, camera); + const fireball = this.game.entities.get_entity_as_fireball(this.entityId); + if (!fireball) { + throw new Error("Fireball not found"); + } + + this.renderObject( + new Vector3D([fireball.pos.x, fireball.pos.y, fireball.pos.z]), + camera + ); } setup() { diff --git a/apps/web-client/src/services/api-service.ts b/apps/web-client/src/services/api-service.ts index 948f7f3..e532f6c 100644 --- a/apps/web-client/src/services/api-service.ts +++ b/apps/web-client/src/services/api-service.ts @@ -1,13 +1,3 @@ import { IGameMetadata } from "@craft/engine"; -import { AppConfig } from "../appConfig"; - -export class ApiServiceClass { - constructor(private baseUrl = AppConfig.api.baseUrl) {} - - async getWorlds(): Promise { - const response = await fetch(`${this.baseUrl}/worlds`); - return await response.json(); - } -} export const ApiService = new ApiServiceClass(); diff --git a/apps/web-client/src/services/entity-sync-checker.ts b/apps/web-client/src/services/entity-sync-checker.ts new file mode 100644 index 0000000..3b46109 --- /dev/null +++ b/apps/web-client/src/services/entity-sync-checker.ts @@ -0,0 +1,126 @@ +import { Game } from "@craft/rust-world"; +import { SerializedEntities } from "@craft/engine"; + +function getPositionFromComponents( + components: [string, string][] +): { x: number; y: number; z: number } | null { + const posComponent = components.find(([name]) => + name.includes("FineWorldPos") + ); + if (!posComponent) return null; + return JSON.parse(posComponent[1]); +} + +/** + * Entity sync checker for comparing client and server entity states. + * Useful for debugging multiplayer synchronization issues. + */ +export class EntitySyncChecker { + private syncCheckInterval: number | null = null; + + constructor( + private game: Game, + private gameId: string, + private serverUrl: string + ) {} + + start(intervalMs = 1000) { + if (this.syncCheckInterval) { + this.stop(); + } + + console.log( + `[Sync] Starting entity sync check every ${intervalMs}ms for game ${this.gameId}` + ); + + this.syncCheckInterval = window.setInterval(async () => { + await this.checkSync(); + }, intervalMs); + } + + stop() { + if (this.syncCheckInterval) { + clearInterval(this.syncCheckInterval); + this.syncCheckInterval = null; + console.log("[Sync] Stopped entity sync check"); + } + } + + private async checkSync() { + try { + const response = await fetch( + `${this.serverUrl}/game/${this.gameId}/entities` + ); + if (!response.ok) { + console.error( + "[Sync] Failed to fetch server entities:", + response.statusText + ); + return; + } + + const data = (await response.json()) as SerializedEntities; + const serverEntities = data.entities; + + for (const serverEntity of serverEntities) { + const localEntity = this.game.getEntityById(serverEntity.id); + if (!localEntity) { + console.log(`[Sync] Entity ${serverEntity.id} missing locally`); + continue; + } + + const serverPos = getPositionFromComponents(serverEntity.components); + if (!serverPos) { + console.log(`[Sync] Entity ${serverEntity.id} missing position`); + continue; + } + + // Get local position from the wasm Entity object + const localPlayer = this.game.getEntityAsPlayer(serverEntity.id); + if (!localPlayer) { + console.log(`[Sync] Entity ${serverEntity.id} missing local player`); + continue; + } + + const localPos = localPlayer.pos; + if (!localPos) { + console.log( + `[Sync] Entity ${serverEntity.id} missing local position` + ); + continue; + } + + const posDiff = Math.sqrt( + Math.pow(localPos.x - serverPos.x, 2) + + Math.pow(localPos.y - serverPos.y, 2) + + Math.pow(localPos.z - serverPos.z, 2) + ); + console.log("posDiff", posDiff, "for entity", serverEntity.id); + + if (posDiff > 0.01) { + // Threshold for "different" + console.log( + `[Sync] Entity ${serverEntity.id} position diff: ${posDiff.toFixed( + 3 + )}` + ); + console.log( + ` Local: (${localPos.x.toFixed(2)}, ${localPos.y.toFixed( + 2 + )}, ${localPos.z.toFixed(2)})` + ); + console.log( + ` Server: (${serverPos.x.toFixed(2)}, ${serverPos.y.toFixed( + 2 + )}, ${serverPos.z.toFixed(2)})` + ); + } + } + + // Apply server-authoritative entity state + this.game.replaceEntities(data); + } catch (err) { + console.error("[Sync] Failed to fetch server entities:", err); + } + } +} diff --git a/apps/web-client/src/services/mp-games-service.ts b/apps/web-client/src/services/mp-games-service.ts index fd63223..bf56cb3 100644 --- a/apps/web-client/src/services/mp-games-service.ts +++ b/apps/web-client/src/services/mp-games-service.ts @@ -1,30 +1,91 @@ import { - IGameMetadata, - ISocketWelcomePayload, - ICreateGameOptions, - Game, - GameAction, + IServerGameMetadata, ISocketMessageType, - PlayerAction, SocketMessage, - IGamesService, - IContructGameOptions, + WelcomeMessage, } from "@craft/engine"; -import { SocketListener } from "../socket"; -import { SocketInterface, getMyUid } from "../app"; -import { ApiService } from "../services/api-service"; -import { GameScript } from "@craft/engine/game-script"; -import { BasicGScript } from "../game-scripts/basic-gscript"; - -export class NetworkGamesService implements IGamesService { - private async waitForWelcomeMessage() { +import { SocketHandler, SocketListener } from "./socket-service"; +import { AppConfig } from "../appConfig"; +import { + ChunkFetcher, + CreateGameOptions, + Entities, + Entity, + EntityActionDto, + Game, + SandBoxGScript, + ServerChunkLoader, +} from "@craft/rust-world"; +import { getMyUid } from "../utils"; +import { GameRendererGameScript } from "../renders/game-renderer"; +import { + addGameRenderer, + addHudRenderer, + addPlayerController, + loadInitialChunks, + RunGameError, + RunningGame, +} from "./running-game"; + +export const SocketInterface = new SocketHandler(); + +const baseUrl = AppConfig.api.baseUrl; + +export async function getAllGames(): Promise { + const response = await fetch(`${baseUrl}/games`); + return await response.json(); +} + +export async function create(options: CreateGameOptions): Promise { + const optionsJson = options.to_js(); + console.log("Creating game", optionsJson); + const response = await fetch(`${baseUrl}/game`, { + method: "POST", + body: JSON.stringify(optionsJson), + headers: { + "Content-Type": "application/json", + }, + }); + return await response.text(); +} + +export async function start(gameId: string): Promise { + await fetch(`${baseUrl}/game/${gameId}/start`, { + method: "POST", + }); +} + +export async function run( + uiMessage: (message: string) => void, + gameId: string +): Promise { + // ===== Join Game ===== + async function joinGame(gameId: string): Promise { + SocketInterface.send( + SocketMessage.make(ISocketMessageType.joinWorld, { + gameId, + myUid: getMyUid(), + }) + ); + + const welcomeMessage = await waitForWelcomeMessage(); + console.log("Welcome message", welcomeMessage); + + if (!welcomeMessage) { + throw new Error("Server didn't create the world"); + } + return welcomeMessage; + } + + async function waitForWelcomeMessage() { let listener: SocketListener | null = null; - const welcomeMessage: ISocketWelcomePayload | null = await new Promise( + const welcomeMessage: WelcomeMessage | null = await new Promise( (resolve) => { listener = (message) => { + console.log("SocketMessage", message); if (message.isType(ISocketMessageType.welcome)) { resolve(message.data); - } else if (message.isType(ISocketMessageType.worldNotFound)) { + } else if (message.isType(ISocketMessageType.failedToJoin)) { resolve(null); console.error("Requested world not found"); } @@ -36,131 +97,91 @@ export class NetworkGamesService implements IGamesService { return welcomeMessage; } - private async buildGame(constructGame: IContructGameOptions) { - const gameSaver = { - save: async (game: Game) => { - this.saveGame(game); - }, - }; + uiMessage("Connecting to game server..."); - const game = Game.make(constructGame, gameSaver); + await SocketInterface.connect(() => { + console.error("Socket disconnected"); + }); - const basic = game.addGameScript(BasicGScript); - game.addGameScript(ServerSideGameScript, basic); + uiMessage("Starting game..."); - return game; - } - - public async createGame(options: ICreateGameOptions): Promise { - SocketInterface.send( - SocketMessage.make(ISocketMessageType.newWorld, { - myUid: getMyUid(), - ...options, - }) - ); + await start(gameId); - console.log("Creating world"); + uiMessage("Joining game..."); - const welcomeMessage = await this.waitForWelcomeMessage(); + const welcomeMessage = await joinGame(gameId); - if (!welcomeMessage) { - throw new Error("Server didn't create the world"); - } + console.log("Joined game", welcomeMessage); - console.log("Welcome Message", welcomeMessage); + // ===== Deserialize Game ===== + const entities = Entities.deserialize(welcomeMessage.entities); - return this.buildGame(welcomeMessage.game); - } + const game = Game.build( + gameId, + null, + null, + entities, + null, + ChunkFetcher.makeFromServerChunkLoader( + new ServerChunkLoader(baseUrl, gameId) + ) + ); + (window as any).game = game; - public async getGame(gameId: string): Promise { - SocketInterface.send( - SocketMessage.make(ISocketMessageType.joinWorld, { - worldId: gameId, - myUid: getMyUid(), - }) - ); + // ===== Game Scripts ===== + game.ensureScript(GameRendererGameScript.name); + game.ensureScript(SandBoxGScript.name()); + game.add_all_scripts(); - const welcomeMessage = await this.waitForWelcomeMessage(); + // ===== Main Player ===== + const myUid = getMyUid(); + console.log("My UID", myUid); - if (!welcomeMessage) { - return null; - } + // ===== Running Game ===== + const runningGame = new RunningGame(game, myUid, true); - return this.buildGame(welcomeMessage.game); - } + // ===== Load Initial Chunks ===== + await loadInitialChunks(runningGame, uiMessage); - public async getAllGames(): Promise { - return await ApiService.getWorlds(); - } + // ===== Game Renderer ===== + const gameRenderer = await addGameRenderer(runningGame, uiMessage); - // we might not have to send the data to the server here. Just tell the server that we want to save and it will - // use its local copy of the game to save - public async saveGame(gameData: Game): Promise { + // ===== Add Action Listener ===== + const onAction = (action: EntityActionDto) => { SocketInterface.send( - SocketMessage.make(ISocketMessageType.saveWorld, { - worldId: gameData.gameId, - }) - ); - } - - public async deleteGame(_gameId: string) { - // TO-DO implement this (REST) - } -} - -export class ServerSideGameScript extends GameScript { - name = "server-side"; - - debug = true; - - constructor(game: Game, private basic: BasicGScript) { - super(game); - } - - setup() { - console.log("Setting up ServerSideGameScript"); - SocketInterface.addListener(this.onSocketMessage.bind(this)); - - this.basic.playerActionService.addActionListener( - this.basic.mainPlayer.uid, - this.onPlayerAction.bind(this) + SocketMessage.make(ISocketMessageType.actions, action.to_js()) ); - } - - onGameAction(action: GameAction) { - if (this.debug) { - console.log("Sending game action", action); + }; + runningGame.onActionListeners.addListener(onAction, "onAction"); + + // ===== Add Socket Listener ===== + SocketInterface.addListener((message) => { + console.log("Got actions message from server", message); + if (message.isType(ISocketMessageType.actions)) { + const action = message.data; + const actionDto = EntityActionDto.from_js(action); + game.handleAction(actionDto); } - SocketInterface.send( - SocketMessage.make(ISocketMessageType.actions, action.getDto()) - ); - } - - onPlayerAction(action: PlayerAction) { - if (this.debug) { - console.log("Sending player action", action); + if (message.isType(ISocketMessageType.newPlayer)) { + const player = message.data; + game.schedule_entity_insert(Entity.from_js(player)); } - SocketInterface.send( - SocketMessage.make(ISocketMessageType.playerActions, action.getDto()) - ); - } + // if (message.isType(ISocketMessageType.gameDiff)) { + // const diff = message.data; + // for (const chunkId of diff.updated_chunks) { + // game.request_chunk(ChunkPos.from_id(BigInt(chunkId))); + // } + // } + }); - private onSocketMessage(message: SocketMessage) { - console.log("MP: Got message", message); - const mainPlayer = this.basic.mainPlayer; - const playerActionService = this.basic.playerActionService; + // ===== Add Player Controller ===== + addPlayerController(runningGame, gameRenderer); - if (message.isType(ISocketMessageType.gameDiff)) { - this.game.handleStateDiff(message.data); - } else if (message.isType(ISocketMessageType.playerActions)) { - if (message.data.data.playerUid === mainPlayer.uid) return; + // ===== Hud Renderer ===== + addHudRenderer(runningGame, gameRenderer); - const playerAction = new PlayerAction( - message.data.type, - message.data.data - ); + // ===== Start Game ===== + runningGame.start(); - playerActionService.performAction(playerAction); - } - } + return runningGame; } diff --git a/apps/web-client/src/services/running-game.ts b/apps/web-client/src/services/running-game.ts new file mode 100644 index 0000000..7437a8f --- /dev/null +++ b/apps/web-client/src/services/running-game.ts @@ -0,0 +1,240 @@ +import { EntityActionDto, Game } from "@craft/rust-world"; +import { HudGScript } from "../renders/hud-renderer"; +import { IS_MOBILE, task } from "../utils"; +import { MobileController } from "../controllers/mobileController"; +import { KeyboardPlayerEntityController } from "../controllers/keyboardPlayerController"; +import { GameRenderer } from "../renders/game-renderer"; +import { EntitySyncChecker } from "./entity-sync-checker"; +import { AppConfig } from "../appConfig"; + +export interface RunGameError { + error: string; +} + +// Fixed timestep constants +const FIXED_TIMESTEP_MS = 1000 / 60; // 16.67ms = 60 ticks per second +const MAX_ACCUMULATED_TIME = FIXED_TIMESTEP_MS * 5; // Cap at 5 frames to prevent spiral of death + +function makeListenerGroup(listenerGroupName: string) { + const listeners: Array<{ func: (...args: T) => void; name: string }> = []; + return { + addListener(func: (...args: T) => void, name: string) { + listeners.push({ func, name }); + }, + callAll(...args: T) { + for (const func of listeners) { + console.log("Calling", listenerGroupName, func.name); + func.func(...args); + } + }, + }; +} + +export class RunningGame { + private running = true; + private pendingActions: unknown[] = []; + private accumulatedTime = 0; + private lastFrameTime = performance.now(); + public currentFrameTime = 0; // Exposed for renderers to use + private entitySyncChecker: EntitySyncChecker | null = null; + + constructor( + public game: Game, + public playerId: number, + enableEntitySync = false + ) { + if (enableEntitySync) { + this.entitySyncChecker = new EntitySyncChecker( + this.game, + this.game.id, + AppConfig.api.baseUrl + ); + } + } + + public startListeners = makeListenerGroup<[]>("start"); + public start() { + console.log("Starting game"); + this.startListeners.callAll(); + + // Start entity sync checker if configured + if (this.entitySyncChecker) { + this.entitySyncChecker.start(); + } + + const updateWrapper = async () => { + await this.update(); + if (this.running) { + requestAnimationFrame(updateWrapper); + } + }; + + requestAnimationFrame(updateWrapper); + } + + public cleanupListeners = makeListenerGroup<[]>("cleanup"); + public cleanup() { + console.log("Cleaning up game"); + this.running = false; + + // Stop entity sync checker + if (this.entitySyncChecker) { + this.entitySyncChecker.stop(); + } + + this.cleanupListeners.callAll(); + } + + public updateListeners = makeListenerGroup<[]>("update"); + public async update() { + const start = performance.now(); + const now = performance.now(); + const frameTime = now - this.lastFrameTime; + this.lastFrameTime = now; + this.currentFrameTime = now; + + // Cap accumulated time to prevent spiral of death + this.accumulatedTime = Math.min( + this.accumulatedTime + frameTime, + MAX_ACCUMULATED_TIME + ); + + // Drain pending actions from JS queue into Rust queue + // This must happen in a synchronous block before any awaits + for (const actionData of this.pendingActions) { + this.game.handleAction(EntityActionDto.from_js(actionData)); + } + this.pendingActions = []; + this.game.handle_actions(); + + // Run fixed timestep updates + while (this.accumulatedTime >= FIXED_TIMESTEP_MS) { + this.game.run_scripts(FIXED_TIMESTEP_MS); + this.accumulatedTime -= FIXED_TIMESTEP_MS; + } + + await task(); + this.game.add_new_entities(); + await task(); + this.game.remove_entities(); + this.game.add_single_chunk(); + this.game.add_blocks(); + await task(); + this.game.remove_blocks(); + this.updateListeners.callAll(); + const end = performance.now(); + if (end - start > 50) { + console.warn("Large update happened. Time: ", end - start); + } + } + + public onActionListeners = makeListenerGroup<[EntityActionDto]>("onAction"); + public onAction(action: EntityActionDto) { + console.log("On Action", action); + const serializedAction = action.to_js(); + // Queue in JS to avoid borrow conflicts during async update loop + this.pendingActions.push(serializedAction); + // Notify listeners with a copy + this.onActionListeners.callAll(EntityActionDto.from_js(serializedAction)); + } + + /** + * Queue an action from external sources (e.g., socket messages). + * The action data should already be serialized JS object. + */ + public queueAction(actionData: unknown) { + this.pendingActions.push(actionData); + } + + public saveListeners = makeListenerGroup<[]>("save"); + public save() { + this.saveListeners.callAll(); + } +} + +export function addPlayerController( + runningGame: RunningGame, + gameRenderer: GameRenderer +) { + const getPlayerController = (runningGame: RunningGame) => { + if (IS_MOBILE) { + return new MobileController(runningGame.onAction, runningGame.playerId); + } + return new KeyboardPlayerEntityController( + runningGame.game, + runningGame.onAction.bind(runningGame), + runningGame.save, + runningGame.playerId, + gameRenderer + ); + }; + const playerController = getPlayerController(runningGame); + runningGame.updateListeners.addListener(() => playerController.update(), "update"); +} + +export async function addGameRenderer( + runningGame: RunningGame, + uiMessage: (message: string) => void +) { + const gameRenderer = new GameRenderer(runningGame.game, runningGame.playerId); + const update = () => { + gameRenderer.update(); + // Pass actual timestamp to fix FPS counter (was hardcoded to 0) + gameRenderer.renderLoop(runningGame.currentFrameTime); + }; + const cleanup = () => { + gameRenderer.cleanup(); + }; + runningGame.updateListeners.addListener(update, "update"); + runningGame.cleanupListeners.addListener(cleanup, "cleanup"); + + uiMessage("Painting the world..."); + await task(); + gameRenderer.update(); + + return gameRenderer; +} + +export function addHudRenderer( + runningGame: RunningGame, + gameRenderer: GameRenderer +) { + const hudRenderer = new HudGScript( + runningGame.game, + gameRenderer, + runningGame.playerId + ); + const update = () => { + hudRenderer.update(0); + }; + const cleanup = () => { + hudRenderer.cleanup(); + }; + runningGame.updateListeners.addListener(update, "update"); + runningGame.cleanupListeners.addListener(cleanup, "cleanup"); + return hudRenderer; +} + +export async function loadInitialChunks( + runningGame: RunningGame, + uiMessage: (message: string) => void +) { + const { game } = runningGame; + console.log("Loading initial chunks"); + async function task() { + await new Promise((resolve) => setTimeout(resolve, 0)); + } + + let pendingChunkCount = game.getPendingChunkCount(); + const initialChunkCount = pendingChunkCount; + while (pendingChunkCount > 0) { + uiMessage( + `Loading chunks... ${ + initialChunkCount - pendingChunkCount + } / ${initialChunkCount}` + ); + await task(); + game.add_single_chunk(); + pendingChunkCount = game.getPendingChunkCount(); + } +} diff --git a/apps/web-client/src/socket.ts b/apps/web-client/src/services/socket-service.ts similarity index 97% rename from apps/web-client/src/socket.ts rename to apps/web-client/src/services/socket-service.ts index 3301e64..0d1f5f3 100644 --- a/apps/web-client/src/socket.ts +++ b/apps/web-client/src/services/socket-service.ts @@ -1,5 +1,5 @@ import { ISocketMessageType, SocketMessage } from "@craft/engine"; -import { AppConfig } from "./appConfig"; +import { AppConfig } from "../appConfig"; export type SocketListener = (message: SocketMessage) => void; diff --git a/apps/web-client/src/services/sp-games-service.ts b/apps/web-client/src/services/sp-games-service.ts index 65aab45..855562a 100644 --- a/apps/web-client/src/services/sp-games-service.ts +++ b/apps/web-client/src/services/sp-games-service.ts @@ -1,14 +1,107 @@ import { - Game, - IGameMetadata, + IApiGameMetadata, ISerializedGame, - ICreateGameOptions, - IGameSaver, - IGamesService, - SandboxGScript, + deserializeGame, + serializeGame, } from "@craft/engine"; +import { CreateGameOptions, Game } from "@craft/rust-world"; +import { getMyUid } from "../utils"; +import { SandBoxGScript } from "@craft/rust-world"; +import { GameRendererGameScript } from "../renders/game-renderer"; +import { + addGameRenderer, + addHudRenderer, + addPlayerController, + loadInitialChunks, + RunningGame, +} from "./running-game"; +import { RunGameError } from "./running-game"; + +const log = (...message: any[]) => { + console.log("sp-games-service.ts: ", ...message); +}; + +export async function create(options: CreateGameOptions): Promise { + log("Creating new game"); + const startCreation = performance.now(); + const game = Game.create(options); + const endCreation = performance.now(); + log("Created new game in", endCreation - startCreation, "ms"); + log("Saving game"); + const startSaving = performance.now(); + await spGameService.saveGame(game); + const endSaving = performance.now(); + log("Saved game in", endSaving - startSaving, "ms"); + return game.id; +} + +export async function run( + uiMessage: (message: string) => void, + id: string +): Promise { + log("Starting game", id); + + // ===== Getting or Creating Game ===== + let game: Game | null = null; + uiMessage("Checking records..."); + + const serializedGame = await spGameService.getGame(id); + if (!serializedGame) { + return { + error: "Game with id " + id + " not found", + }; + } + + uiMessage("Loading game"); + + const start = performance.now(); + game = deserializeGame(serializedGame); + const end = performance.now(); + log("Deserialized game in", end - start, "ms"); + + log("The Game", game); + (window as any).game = game; + + // ===== Main Player ===== + const mainPlayerUid = getMyUid(); + game.makeAndAddPlayer(mainPlayerUid); + game.add_new_entities(); + + // ===== Game Scripts ===== + log("Ensuring scripts"); + game.ensureScript(SandBoxGScript.name()); + game.ensureScript(GameRendererGameScript.name); + game.add_all_scripts(); -export class ClientDbGamesService implements IGamesService { + // ===== Running Game ===== + const runningGame = new RunningGame(game, mainPlayerUid); + + // ===== Load Initial Chunks ===== + await loadInitialChunks(runningGame, uiMessage); + + // ===== Game Renderer ===== + const gameRenderer = await addGameRenderer(runningGame, uiMessage); + + // ===== Player Controller ===== + // TODO: Remove the gameRenderer requirement so we can do this earlier on + addPlayerController(runningGame, gameRenderer); + + // ===== Hud Renderer ===== + // TODO: Remove the gameRenderer requirement so we can do this earlier on + addHudRenderer(runningGame, gameRenderer); + + // ===== Add Saving ===== + runningGame.saveListeners.addListener(() => { + spGameService.saveGame(game); + }, "save"); + + // ===== Start Game ===== + runningGame.start(); + + return runningGame; +} + +export class ClientDbGamesService { private static WORLDS_OBS = "worlds"; static async factory() { @@ -46,24 +139,7 @@ export class ClientDbGamesService implements IGamesService { private constructor(private db: IDBDatabase) {} - async createGame( - createGameOptions: ICreateGameOptions | ISerializedGame - ): Promise { - const gameSaver = this.getGameSaver(); - const game = Game.make(createGameOptions, gameSaver); - game.addGameScript(SandboxGScript); - return game; - } - - private getGameSaver(): IGameSaver { - return { - save: async (game: Game) => { - this.saveGame(game); - }, - }; - } - - getAllGames(): Promise { + getAllGames(): Promise { return new Promise((resolve) => { const transaction = this.db.transaction([ ClientDbGamesService.WORLDS_OBS, @@ -89,7 +165,28 @@ export class ClientDbGamesService implements IGamesService { }); } - async getGame(gameId: string): Promise { + async hasGame(gameId: string): Promise { + return new Promise((resolve, reject) => { + const transaction = this.db.transaction( + [ClientDbGamesService.WORLDS_OBS], + "readonly" + ); + const objectStore = transaction.objectStore( + ClientDbGamesService.WORLDS_OBS + ); + + // `getKey` is supported in modern browsers, lighter than `get` + const request = objectStore.getKey(gameId); + + request.onsuccess = (event: any) => { + resolve(event.target.result !== undefined); // key exists if result is not undefined + }; + + request.onerror = () => reject(request.error); + }); + } + + async getGame(gameId: string): Promise { const foundGame: ISerializedGame | null = await new Promise((resolve) => { const transaction = this.db.transaction([ ClientDbGamesService.WORLDS_OBS, @@ -112,26 +209,30 @@ export class ClientDbGamesService implements IGamesService { if (!foundGame) return null; - return this.createGame(foundGame); + return foundGame; } async saveGame(data: Game) { - const transaction = this.db.transaction( - [ClientDbGamesService.WORLDS_OBS], - "readwrite" - ); - - console.log("Saving game", data); + log("Saving game", data); + return new Promise((resolve, reject) => { + const transaction = this.db.transaction( + [ClientDbGamesService.WORLDS_OBS], + "readwrite" + ); + const serializedGame = serializeGame(data); - transaction.oncomplete = () => { - console.log("All done!"); - }; - transaction.onerror = () => { - console.log("There was an error", event); - }; - const objStore = transaction.objectStore("worlds"); + transaction.oncomplete = async () => { + log("Saving game complete"); + resolve(); + }; + transaction.onerror = () => { + console.log("There was an error", event); + reject(event); + }; + const objStore = transaction.objectStore(ClientDbGamesService.WORLDS_OBS); - objStore.put(data.serialize()); + objStore.put(serializedGame); + }); } async deleteGame(gameId: string) { @@ -151,3 +252,5 @@ export class ClientDbGamesService implements IGamesService { objStore.delete(gameId); } } + +export const spGameService = await ClientDbGamesService.factory(); diff --git a/apps/web-client/src/textureMapper.ts b/apps/web-client/src/services/texture-mapping-service.ts similarity index 92% rename from apps/web-client/src/textureMapper.ts rename to apps/web-client/src/services/texture-mapping-service.ts index eae31e0..bb84485 100644 --- a/apps/web-client/src/textureMapper.ts +++ b/apps/web-client/src/services/texture-mapping-service.ts @@ -1,5 +1,4 @@ -import { Item, ThrowableItem } from "@craft/engine/item"; -import { BlockType } from "@craft/rust-world"; +import { BlockType, Item } from "@craft/rust-world"; const TEXTURE_ATLAS_WIDTH = 4; const TEXTURE_ATLAS_HEIGHT = 4; @@ -7,8 +6,10 @@ const TEXTURE_ATLAS_HEIGHT = 4; const xStepVal = 1 / TEXTURE_ATLAS_WIDTH; const yStepVal = 1 / TEXTURE_ATLAS_HEIGHT; +type ItemKey = BlockType | "Fireball"; + const textureData = new Map< - Item, + ItemKey, { offsetX: number; offsetY: number } | null >(); textureData.set(BlockType.Grass, { offsetX: 0, offsetY: 0 }); @@ -21,7 +22,7 @@ textureData.set(BlockType.RedFlower, { offsetX: 0, offsetY: 2 }); textureData.set(BlockType.Water, { offsetX: 2, offsetY: 2 }); textureData.set(BlockType.Planks, { offsetX: 3, offsetY: 0 }); textureData.set(BlockType.Red, { offsetX: 3, offsetY: 2 }); -textureData.set(ThrowableItem.Fireball, { offsetX: 3, offsetY: 1 }); +textureData.set("Fireball", { offsetX: 3, offsetY: 1 }); class Textures { private getTextureData(type: BlockType) { @@ -68,7 +69,17 @@ class Textures { } public getBlockPreviewCords(type: Item, width: number, height: number) { - const { offsetX, offsetY } = textureData.get(type)!; + const itemKey = + typeof type === "object" && "Block" in type ? type.Block : type; + const data = textureData.get(itemKey); + if (!data) { + console.log(textureData); + throw new Error( + `Texture data for texture ${JSON.stringify(type)} was not found` + ); + } + + const { offsetX, offsetY } = data; return { x1: offsetX * xStepVal * width, diff --git a/apps/web-client/src/utils.ts b/apps/web-client/src/utils.ts index 9debbfc..e57a254 100644 --- a/apps/web-client/src/utils.ts +++ b/apps/web-client/src/utils.ts @@ -4,6 +4,51 @@ export function getEleOrError(id: string): T { return ele as T; } +export function getEle(id: string): T | undefined { + const ele = document.getElementById(id); + if (!ele) { + return undefined; + } + return ele as T; +} + +// export function hideElement(e: HTMLElement) { +// e.style.display = "none"; +// } + +export function showElement(e: HTMLElement) { + e.classList.remove("hidden"); + e.classList.add("shown"); +} + export function hideElement(e: HTMLElement) { - e.style.display = "none"; + e.classList.add("hidden"); + e.classList.remove("shown"); +} + +// generate your unique id +const UID_KEY = "tylercraft-user-id"; +if (!localStorage.getItem(UID_KEY)) { + const randomNum = Math.floor(Math.random() * 10000000); + localStorage.setItem(UID_KEY, randomNum.toString()); +} + +export function getMyUid() { + // check url for uid override + const urlParams = new URLSearchParams(window.location.search); + const uidOverride = urlParams.get("uid"); + if (uidOverride) { + return Number(uidOverride); + } + + const uid = Number(localStorage.getItem(UID_KEY)); + if (!uid) throw new Error("UID not defined"); + return uid; +} + +export const IS_MOBILE = /Mobi/.test(window.navigator.userAgent); +console.log("Is Mobile: ", IS_MOBILE); + +export async function task() { + await new Promise((resolve) => setTimeout(resolve, 0)); } diff --git a/apps/web-client/src/world-picker.tsx b/apps/web-client/src/world-picker.tsx deleted file mode 100644 index 991f35f..0000000 --- a/apps/web-client/src/world-picker.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react"; -import { IGameMetadata } from "@craft/engine"; - -interface Props { - games: IGameMetadata[]; - onGameSelect: (game: IGameMetadata) => void; - onNewGame: () => void; -} - -export const renderWorldPicker = (props: Props) => { - return ( -
- {props.games.map((game) => ( - - ))} - -
- ); -}; diff --git a/apps/web-client/tsconfig.json b/apps/web-client/tsconfig.json index 9135dfe..c2c2b8c 100644 --- a/apps/web-client/tsconfig.json +++ b/apps/web-client/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./build", - "lib": ["es2019", "dom", "WebWorker"], + "lib": ["es2020", "dom", "WebWorker"], "skipLibCheck": true, "isolatedModules": true, "module": "ESNext", diff --git a/apps/web-client/vite.config.js b/apps/web-client/vite.config.js index ac0c786..bcd55d0 100644 --- a/apps/web-client/vite.config.js +++ b/apps/web-client/vite.config.js @@ -2,6 +2,7 @@ import { defineConfig } from "vite"; import wasm from "vite-plugin-wasm"; import topLevelAwait from "vite-plugin-top-level-await"; import react from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ optimizeDeps: { @@ -12,8 +13,23 @@ export default defineConfig({ commonjsOptions: { include: [/@craft\/engine/, /node_modules/], }, + // rollupOptions: { + // input: { + // index: "./index1.html", + // test: "./src/index2.html", + // }, + // }, }, - plugins: [react(), wasm(), topLevelAwait()], + server: { + allowedHosts: [ + "localhost", + "127.0.0.1", + "0.0.0.0", + "bd99-66-54-100-22.ngrok-free.app", + ], + }, + + plugins: [tailwindcss(), react(), wasm(), topLevelAwait()], worker: { format: "es", plugins: () => [wasm(), topLevelAwait()], diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..45fa1e7 Binary files /dev/null and b/bun.lockb differ diff --git a/lib/engine/world/biome.ts b/lib/engine/STUFF_TO_RUST/biome.ts similarity index 99% rename from lib/engine/world/biome.ts rename to lib/engine/STUFF_TO_RUST/biome.ts index 0195a55..2e4dbec 100644 --- a/lib/engine/world/biome.ts +++ b/lib/engine/STUFF_TO_RUST/biome.ts @@ -1,5 +1,5 @@ import { Random } from "../utils/random.js"; -import { Vector2D, VectorIndex } from "../utils/vector.js"; +import { Vector2D, VectorIndex } from "../src/vector.js"; export enum Biome { Plains, diff --git a/lib/engine/world/terrainGenerator.ts b/lib/engine/STUFF_TO_RUST/terrainGenerator.ts similarity index 98% rename from lib/engine/world/terrainGenerator.ts rename to lib/engine/STUFF_TO_RUST/terrainGenerator.ts index ec39867..30c3585 100644 --- a/lib/engine/world/terrainGenerator.ts +++ b/lib/engine/STUFF_TO_RUST/terrainGenerator.ts @@ -1,12 +1,12 @@ -import { Vector2D, Vector3D } from "../utils/vector.js"; -import { CONFIG } from "../config.js"; +import { Vector2D, Vector3D } from "../src/vector.js"; +import { CONFIG } from "../src/config.js"; import { Random } from "../utils/random.js"; import CubeHelpers, { Cube } from "../entities/cube.js"; -import { World } from "./world.js"; +import { World } from "../world/world.js"; import { BiomeGenerator, Biome } from "./biome.js"; import { WorldModule } from "../modules.js"; import { BlockType } from "@craft/rust-world"; -import { ISerializedChunk } from "./index.js"; +import { ISerializedChunk } from "../world/index.js"; // export interface ISerializedTerrainGenerator { // blocksToRender: Array<{ diff --git a/lib/engine/camera.ts b/lib/engine/camera.ts deleted file mode 100644 index 2901bb2..0000000 --- a/lib/engine/camera.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Entity, FaceLocater } from "./entities/entity.js"; -import { Vector3D } from "./utils/vector.js"; -import { IDim } from "./types.js"; - -export interface ICameraData { - pos: IDim; - rotCart: IDim; -} - -export abstract class Camera { - // (x, y, z) - abstract pos: Vector3D; - // (dist, theta: [0, 2pi], phi: [0, pi]) - abstract rot: Vector3D; - - getCameraData(): ICameraData { - return { - pos: this.pos.data as IDim, - rotCart: this.rot.toCartesianCoords().data as IDim, - }; - } - - update(_delta: number) { - /* NO-OP */ - } - render(_camera: Camera) { - /* NO-OP */ - } - hit(_ent: Entity, _where: FaceLocater) { - /* NO-OP */ - } - - abstract rotateBy(x: number, y: number): void; -} diff --git a/lib/engine/config.ts b/lib/engine/config.ts deleted file mode 100644 index 7489774..0000000 --- a/lib/engine/config.ts +++ /dev/null @@ -1,61 +0,0 @@ -export const BASE_CONFIG = { - seed: "bungi", - - renderDistance: 2, - - /** - * How many chunks to load in each direction starting at the player - */ - loadDistance: 2, - - transparency: true, - - fovFactor: 0.6, - - glFov: (45 * Math.PI) / 180, - - terrain: { - generateChunks: true, - jagFactor: 32, - maxHeight: 12, - cloudLevel: 30, - waterLever: -1, - chunkSize: 16, - // chunkSize: 4, - flatWorld: true, - // flatWorld: true, - // trees: true, - trees: false, - // flowers: true, - flowers: false, - /** - * Make the world load forever in all directions. - * If off the world loads to the size of Config.loadDistance - */ - infiniteGen: true, - }, - - gravity: -0.013, - - player: { - speed: 0.2, - reach: 10, - // jumpSpeed: 0.16, - jumpSpeed: 0.25, - mouseRotSpeed: 0.002, - thirdPersonCamDist: 6, - }, -}; - -export let CONFIG = BASE_CONFIG; - -export type IConfig = typeof CONFIG; - -export function setConfig(config: IConfig) { - CONFIG = { ...config }; -} - -// declare var window; - -// if (window) -// (window as any).config = CONFIG; diff --git a/lib/engine/controllers/controller.ts b/lib/engine/controllers/controller.ts deleted file mode 100644 index 923a3a7..0000000 --- a/lib/engine/controllers/controller.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Game } from "../game.js"; - -export abstract class GameController { - protected game: Game; - - constructor(game: Game) { - this.game = game; - } - - abstract update(delta: number): void; -} diff --git a/lib/engine/controllers/emptyController.ts b/lib/engine/controllers/emptyController.ts deleted file mode 100644 index fe657e5..0000000 --- a/lib/engine/controllers/emptyController.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { GameController } from "./controller.js"; - -export class EmptyController extends GameController { - update(_delta: number): void { - // NO-OP - } -} diff --git a/lib/engine/entities/cube.ts b/lib/engine/entities/cube.ts deleted file mode 100644 index aabcbec..0000000 --- a/lib/engine/entities/cube.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { getBlockData } from "../blockdata.js"; -import { Direction, Vector3D } from "../utils/vector.js"; -import { IDim } from "../types.js"; -import { Entity, FaceLocater } from "./entity.js"; -import { BlockShape, BlockType } from "@craft/rust-world"; - -export type CubeDto = { - type: BlockType; - pos: IDim; -}; - -export type Cube = { - type: BlockType; - pos: Vector3D; -}; - -export type ISerializedCube = { - block_type: BlockType; - extra_data: "None"; - world_pos: { x: number; y: number; z: number }; -}; - -export type WasmCube = { - block_type: BlockType; - world_pos: { x: number; y: number; z: number }; - extraData?: { Image: Direction } | "None"; -}; - -export type Box = { - pos: Vector3D; - dim?: IDim; -}; - -export type HitBox = Box & { - dim: IDim; - hit?: (entity: Entity, where: FaceLocater) => void; -}; - -export const CUBE_DIM: IDim = [1, 1, 1]; - -class CubeHelpersClass { - fromWasmCube(cube: WasmCube): Cube { - try { - return { - pos: new Vector3D([ - cube.world_pos.x, - cube.world_pos.y, - cube.world_pos.z, - ]), - type: cube.block_type, - }; - } catch (err) { - console.log("Could not create cube from wasm cube", cube, err); - throw err; - } - } - - createCube(type: BlockType, pos: Vector3D) { - return { - type, - pos, - }; - } - - deserialize(cubeDto: CubeDto): Cube { - return { - type: cubeDto.type, - pos: new Vector3D(cubeDto.pos), - }; - } - - serialize(cube: Cube): CubeDto { - return { - type: cube.type, - pos: cube.pos.data as IDim, - }; - } - - isPointInsideOfCube(cube: Cube, point: Vector3D) { - return cube.pos.data.every((ord, index) => { - return ( - point.data[index] >= ord && point.data[index] <= ord + CUBE_DIM[index] - ); - }); - } -} - -const CubeHelpers = new CubeHelpersClass(); -export default CubeHelpers; diff --git a/lib/engine/entities/entity.ts b/lib/engine/entities/entity.ts deleted file mode 100644 index b04f406..0000000 --- a/lib/engine/entities/entity.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Game, World } from "../index.js"; -import { IDim } from "../types.js"; -import { Vector3D } from "../utils/vector.js"; -import { Cube } from "./cube.js"; -import { IEntityType } from "./entityType.js"; - -export enum RenderType { - CUBE, - SPHERE, -} - -export interface FaceLocater { - side: number; - dir: 1 | 0; -} - -export enum MetaAction { - right, - left, - forward, - backward, - up, - down, - jump, - fireball, -} - -export interface EntityDto { - uid: string; - pos: IDim; - dim: IDim; - type: IEntityType; -} - -/** - * Should be extended by all non-abstract sub classes - * */ -export interface IEntity { - type: IEntityType; -} - -export abstract class Entity< - DTO extends EntityDto = EntityDto, - DtoNoType = Omit -> { - // Used to mark this entity as changed. - // This will then be sent to the server - dirty = false; - - /* make dirty - * TODO pass in the properties that have changed - */ - protected soil() { - this.dirty = true; - } - - public get isDirty() { - return this.dirty; - } - - pos: Vector3D = new Vector3D([0, 0, 0]); - dim: IDim = [1, 1, 1]; - uid = ""; - - constructor(dto: Partial) { - this.set(dto); - } - - // TODO make the allowable entities generic - abstract type: IEntityType; - - abstract getDto(): DTO; - - protected baseDto(): EntityDto { - return { - uid: this.uid, - pos: this.pos.data as IDim, - dim: this.dim, - type: this.type, - }; - } - - abstract set>(data: T): void; - - protected baseSet(data: Partial) { - this.soil(); - if (data.pos) { - this.pos = new Vector3D(data.pos); - } - if (data.dim) { - this.dim = data.dim; - } - if (data.uid) { - this.uid = data.uid; - } - } - - abstract update(game: Game, world: World, delta: number): void; - - setUid(uid: string) { - this.uid = uid; - } -} diff --git a/lib/engine/entities/entityController.ts b/lib/engine/entities/entityController.ts deleted file mode 100644 index 8da5c2c..0000000 --- a/lib/engine/entities/entityController.ts +++ /dev/null @@ -1,5 +0,0 @@ -export abstract class EntityController { - abstract update(): void; - - abstract cleanup(): void; -} diff --git a/lib/engine/entities/entityHolder.ts b/lib/engine/entities/entityHolder.ts deleted file mode 100644 index e77d9c8..0000000 --- a/lib/engine/entities/entityHolder.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { Game } from "../game.js"; -import { GameStateDiff } from "../gameStateDiff.js"; -import { World } from "../world/world.js"; -import { Entity, EntityDto } from "./entity.js"; -import { IEntityType } from "./entityType.js"; -import { Player } from "./player/player.js"; -import { Projectile } from "./projectile.js"; - -// Types that need to be updated -export const GameEntityClassMap = { - [IEntityType.Player]: Player, - [IEntityType.Projectile]: Projectile, -}; - -// Helper Types -type ValueOfClass = C extends new ( - ...args: any[] -) => infer T - ? T - : never; -type Distribute = U extends GameEntityTypeOfClass ? ValueOfClass : never; - -export type GameEntityDtoMap = { - [key in keyof typeof GameEntityClassMap]: ValueOfClass< - (typeof GameEntityClassMap)[key] - > extends Entity - ? DTO - : never; -}; -export type GameEntityDto = GameEntityDtoMap[keyof GameEntityDtoMap]; -export type GameEntityTypeOfClass = - (typeof GameEntityClassMap)[keyof typeof GameEntityClassMap]; -export type GameEntity = Distribute; -type GameEntityClassTypeLookup = ValueOfClass< - (typeof GameEntityClassMap)[T] ->; - -export interface ISerializedEntities { - entities: GameEntityDto[]; -} - -export class EntityHolder { - private entities: Map = new Map(); // this includes players - private players: Map = new Map(); - - constructor(data?: ISerializedEntities) { - if (data) { - const entityMapData: [uid: string, entity: Entity][] = data.entities.map( - (e) => [e.uid, this.createEntity(e)] - ); - this.entities = new Map(entityMapData); - - const playersMapData: [uid: string, player: Player][] = Array.from( - this.entities.values() - ) - .filter((ent) => ent instanceof Player) - .map((player) => [player.uid, player as Player]); - this.players = new Map(playersMapData); - } - } - - //======================= - // Getters - //======================== - tryGet(uid: string): T | undefined { - return this.entities.get(uid) as T | undefined; - } - - get(id: string): T { - const ent = this.tryGet(id); - if (!ent) { - throw new Error(`Entity ${id} not found`); - } - return ent; - } - getActivePlayers() { - return Array.from(this.players.values()); - } - - //======================= - // Create - //======================= - - createEntity< - T extends EntityDto, - S extends GameEntityClassTypeLookup - >(entity: T): S { - console.log("Creating entity of type: ", entity.type); - const entClass = GameEntityClassMap[entity.type]; - return new entClass(entity) as S; - } - - //======================= - // Update - //======================== - - update(game: Game, world: World, delta: number) { - const entityArray = Array.from(this.entities.values()); - entityArray.forEach((entity) => entity.update(game, world, delta)); - } - - updateEntity(entityDto: Partial & { uid: string }) { - const entity = this.entities.get(entityDto.uid); - if (!entity) return; - entity.set(entityDto as any); - } - - setEntity(stateDiff: GameStateDiff, entityDto: EntityDto) { - const entity = this.createEntity(entityDto); - this.entities.set(entity.uid, entity); - stateDiff.updateEntity(entity.uid); - } - - serialize(): ISerializedEntities { - return { - entities: Array.from(this.players.values()).map((p) => p.getDto()), - }; - } - - add(entity: Entity) { - console.log("Adding entity: ", entity.uid); - if (this.entities.has(entity.uid)) { - throw new Error(`Entity ${entity.uid} already exists`); - } - if (!entity.uid) throw new Error("Must have uid"); - this.entities.set(entity.uid, entity); - } - - createPlayer(uid: string) { - console.log("Creating player: ", uid); - if (this.players.has(uid)) { - throw new Error(`Player ${uid} already exists`); - } - const player = Player.create(uid); - this.players.set(player.uid, player); - this.add(player); - return player; - } - - createOrGetPlayer(uid: string): Player { - // looking to see if we have already loaded this player, if so then return it - const player = this.players.get(uid); - if (player) { - return player; - } - - return this.createPlayer(uid); - } - - remove(uid: string) { - const entity = this.entities.get(uid); - if (!entity) { - console.log("Can't find entity with that uid"); - return; - } - // if (entity instanceof Player) - this.entities.delete(entity.uid); - } - - removePlayer(uid: string) { - const player = this.players.get(uid); - if (!player) { - console.log("Can't find player with that uid"); - return; - } - this.players.delete(player.uid); - this.entities.delete(player.uid); - } - - removeAllPlayers() { - this.players.clear(); - this.entities.forEach((entity) => { - if (entity instanceof Player) { - this.entities.delete(entity.uid); - } - }); - } - - iterable() { - return this.entities.values(); - } -} diff --git a/lib/engine/entities/entityType.ts b/lib/engine/entities/entityType.ts deleted file mode 100644 index 1743b69..0000000 --- a/lib/engine/entities/entityType.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const enum IEntityType { - Player = 0, - Projectile = 1, -} diff --git a/lib/engine/entities/moveableEntity.ts b/lib/engine/entities/moveableEntity.ts deleted file mode 100644 index c472fda..0000000 --- a/lib/engine/entities/moveableEntity.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { IDim } from "../types.js"; -import { bindValue } from "../utils.js"; -import { Vector3D } from "../utils/vector.js"; -import { Entity, EntityDto, MetaAction } from "./entity.js"; - -export interface MovableEntityDto extends EntityDto { - vel: IDim; -} -export interface CameraRay { - pos: { x: number; y: number; z: number }; - rot: { theta: number; phi: number }; -} - -export abstract class MovableEntity< - T extends MovableEntityDto = MovableEntityDto -> extends Entity { - vel = Vector3D.zero; - /** - * (radius (1), theta: [0, 2pi], phi: [0, pi]) - */ - rot = Vector3D.zero; - - onGround = false; - jumpCount = 0; - - metaActions = new Set(); - - protected baseDto(): MovableEntityDto { - return { - ...super.baseDto(), - vel: this.vel.data as IDim, - }; - } - - protected baseSet(data: Partial) { - console.log("baseSet ent", this, data); - super.baseSet(data); - if (data.vel) { - this.vel = new Vector3D(data.vel); - } - } - - rotate(r: Vector3D) { - this.rot = this.rot.add(r); - - // bound the rot to ([0, pi], [0, 2 * pi]) - this.rot.set(0, 1); - this.rot.set(1, bindValue(this.rot.get(1), 0, 2 * Math.PI, true)); - this.rot.set(2, bindValue(this.rot.get(2), 0, Math.PI)); - } - - getRay(): CameraRay { - const eyePos = this.pos.add( - new Vector3D([this.dim[0] / 2, this.dim[1] * (9 / 10), this.dim[2] / 2]) - ); - - return { - pos: { - x: eyePos.get(0), - y: eyePos.get(1), - z: eyePos.get(2), - }, - rot: { - theta: -this.rot.get(1) + (Math.PI * 3) / 2, - // Convert to [-pi/2, pi/2] - phi: -(Math.PI / 2 - this.rot.get(2)), - }, - }; - } -} diff --git a/lib/engine/entities/player/player.ts b/lib/engine/entities/player/player.ts deleted file mode 100644 index b4d9135..0000000 --- a/lib/engine/entities/player/player.ts +++ /dev/null @@ -1,401 +0,0 @@ -import { IEntity } from "../entity.js"; -import { IDim } from "../../types.js"; -import { MovableEntity, MovableEntityDto } from "../moveableEntity.js"; -import { CONFIG } from "../../config.js"; -import { Direction, Vector3D } from "../../utils/vector.js"; -import CubeHelpers from "../cube.js"; -import { Game } from "../../game.js"; -import { IEntityType } from "../entityType.js"; -import { BlockType } from "@craft/rust-world"; -import { Item, ThrowableItem } from "../../item.js"; -import { Projectile } from "../projectile.js"; -import { PlayerAction } from "./playerActions.js"; -import { World } from "../../world/index.js"; - -export interface BeltDto { - selectedBlock: Item; -} - -class Belt { - public selectedIndex = 0; - public length = 10; - - public itemActions: ((game: Game) => void)[] = []; - - public items: Item[] = [ - BlockType.Stone, - BlockType.Gold, - BlockType.Grass, - BlockType.Wood, - BlockType.RedFlower, - BlockType.Cloud, - BlockType.Red, - BlockType.Planks, - BlockType.Leaf, - ThrowableItem.Fireball, - ]; - - get selectedItem() { - return this.items[this.selectedIndex]; - } - - getDto(): BeltDto { - return { - selectedBlock: this.selectedItem, - }; - } - - public getItem(index: number) { - const val = this.items[index]; - if (val) { - return val; - } - return null; - } - - public moveLeft() { - this.selectedIndex = - (this.selectedIndex - 1 + this.items.length) % this.items.length; - console.log("Moved left", this.selectedIndex); - } - - public moveRight() { - this.selectedIndex = (this.selectedIndex + 1) % this.items.length; - console.log("Moved right", this.selectedIndex); - } - - public setIndex(index: number) { - this.selectedIndex = index; - console.log("Set index", this.selectedIndex); - } -} - -export interface PlayerDto extends MovableEntityDto { - type: IEntityType.Player; - moveDirections: Direction[]; - rot: IDim; - belt: BeltDto; - health: { - current: number; - max: number; - }; -} - -// A controller / PlayerHandler will append actions to Player -export class Player extends MovableEntity implements IEntity { - // abstract values - static readonly type = IEntityType.Player; - get type() { - return Player.type; - } - - // Entity overrides - pos: Vector3D = new Vector3D([0, 50, 0]); - dim: IDim = [0.8, 2, 0.8]; - rot = new Vector3D([0, 0, Math.PI / 2]); - - // Player Member Variables - thirdPerson = false; - onGround = false; - distanceMoved = 0; // used for animating the arms and legs. Reset to zero when not moving - - belt = new Belt(); - - leftHandPosition = new Vector3D([1, 1, 0]); - rightHandPosition = new Vector3D([1, 1, 1]); - - health = { - current: 100, - max: 100, - }; - - fire = { - count: 0, - holding: false, - coolDown: 10, - }; - - creative = false; - - moveDirections: Direction[] = []; - - inventoryIndex = 0; - - static create(id: string): Player { - return new Player({ - uid: id, - }); - } - - getDto(): PlayerDto { - return { - ...this.baseDto(), - type: IEntityType.Player, - health: this.health, - rot: this.rot.data as IDim, - moveDirections: this.moveDirections, - belt: this.belt.getDto(), - }; - } - - set(player: Partial) { - super.baseSet(player); - if (player.health) { - this.health = player.health; - } - if (player.moveDirections) { - this.moveDirections = player.moveDirections; - } - if (player.rot) { - this.rot = new Vector3D(player.rot); - } - } - - isJumping = false; - haveDoubleJump = false; - jumpCount = 0; - tryJump() { - if (this.onGround) { - this.isJumping = true; - return; - } - if (!this.haveDoubleJump) { - this.isJumping = true; - this.haveDoubleJump = true; - } - } - - setCreative(val: boolean) { - console.log("Setting creative to", val); - this.creative = val; - } - - hurt(amount: number) { - this.health.current -= amount; - } - - godForce(): Vector3D | null { - const baseSpeed = CONFIG.player.speed; - - const moveDirection = (direction: Direction) => { - switch (direction) { - case Direction.Forwards: - return new Vector3D([-baseSpeed, this.rot.get(1), Math.PI / 2]) - .toCartesianCoords() - .set(1, 0); - case Direction.Backwards: - return new Vector3D([baseSpeed, this.rot.get(1), Math.PI / 2]) - .toCartesianCoords() - .set(1, 0); - case Direction.Left: - return new Vector3D([ - baseSpeed, - this.rot.get(1) + Math.PI / 2, - Math.PI / 2, - ]) - .toCartesianCoords() - .set(1, 0); - case Direction.Right: - return new Vector3D([ - baseSpeed, - this.rot.get(1) - Math.PI / 2, - Math.PI / 2, - ]) - .toCartesianCoords() - .set(1, 0); - case Direction.Up: - if (this.creative) { - return new Vector3D([0, baseSpeed, 0]); - } else { - return Vector3D.zero; - } - case Direction.Down: - if (this.creative) { - return new Vector3D([0, -baseSpeed, 0]); - } else { - return Vector3D.zero; - } - } - }; - - let desiredVel = Vector3D.zero; - if (this.creative) { - desiredVel.set(1, 0); - } else { - desiredVel.set(1, this.vel.get(1)); - } - for (const dir of this.moveDirections) { - const vel = moveDirection(dir); - desiredVel = desiredVel.add(vel); - } - const currentVel = this.vel; - - let force = desiredVel.sub(currentVel); - - if (force.magnitude() > 0.025) { - force = force.normalize().scalarMultiply(0.025); - } - - return force; - } - - jumpForce(): Vector3D | null { - if (this.creative) { - return null; - } - if (!this.isJumping) { - return null; - } - this.isJumping = false; - - const diffYVel = CONFIG.player.jumpSpeed - this.vel.get(1); - return new Vector3D([0, diffYVel, 0]); - } - - gravityForce(): Vector3D | null { - if (this.creative) { - return null; - } - if (this.onGround) { - return null; - } - return new Vector3D([0, CONFIG.gravity, 0]); - } - - update(_game: Game, world: World, delta: number) { - const jumpForce = this.jumpForce(); - const gravityForce = this.gravityForce(); - const godForce = this.godForce(); - - const totalForce = ( - [godForce, jumpForce, gravityForce].filter((f) => f) as Vector3D[] - ).reduce((acc: Vector3D, f: Vector3D) => acc.add(f), Vector3D.zero); - - this.vel = this.vel.add(totalForce); - - // We did move - if (this.vel.magnitude() > 0) { - const scaledVel = this.vel.scalarMultiply(delta / 16); - const newPos = world.tryMove(this, scaledVel); - const actualVel = newPos.sub(this.pos); - this.pos = newPos; - - const moveDist = Math.abs(actualVel.get(0)) + Math.abs(actualVel.get(2)); - if (moveDist > 0) { - this.distanceMoved += moveDist; - } else { - this.distanceMoved = 0; - } - } else { - this.distanceMoved = 0; - } - - // set terminal velocity - // if (this.vel.get(1) < -0.9) { - // this.vel.set(1, -0.9); - // } - - if (this.fire.count > 0 && !this.fire.holding) this.fire.count--; - - // Prevent from falling out of the world - if (this.pos.get(1) < -10) { - this.pos.set(1, 30); - this.vel.set(1, -0.1); - } - - // Am I on the ground? (Only need to check if I have moved) - const belowPos = this.pos.add(new Vector3D([0, -0.1, 0])); - const intersectingPoss = world.getIntersectingBlocksWithEntity( - belowPos, - new Vector3D(this.dim) - ); - - if (intersectingPoss.length > 0) { - this.vel.set(1, 0); - this.onGround = true; - this.isJumping = false; - this.haveDoubleJump = false; - } else { - this.onGround = false; - } - } - - doPrimaryAction(game: Game) { - const item = this.belt.selectedItem; - - console.log("Doing primary action", item); - - if (item === ThrowableItem.Fireball) { - this.fireball(game); - } else { - this.placeBlock(game, item); - } - } - - doSecondaryAction(game: Game) { - const ray = this.getRay(); - const lookingData = game.world.lookingAt(ray); - if (!lookingData) return; - const { cube } = lookingData; - if (!cube) return; - game.removeBlock(cube); - } - - private actionListeners: ((action: PlayerAction) => void)[] = []; - addActionListener(listener: (action: PlayerAction) => void) { - this.actionListeners.push(listener); - } - - // Right now this just send the action, the handling happens in playerAction.ts - handleAction(action: PlayerAction) { - console.log("Handling actionin palyer", action); - for (const listener of this.actionListeners) { - console.log("Calling listener"); - listener(action); - } - } - - // Player actions - placeBlock(game: Game, blockType: BlockType) { - const ray = this.getRay(); - const lookingData = game.world.lookingAt(ray); - if (!lookingData) return; - console.log("Looking at data", lookingData); - const { cube } = lookingData; - if (!cube) return; - - const newCubePos = lookingData.cube.pos.add( - Vector3D.fromDirection(lookingData.face) - ); - - const newCube = CubeHelpers.createCube(blockType, newCubePos); - - console.log("Placed Cube", newCube); - - game.placeBlock(newCube); - } - - fireball(game: Game) { - if (this.fire.count > 0) return; - - const vel = this.rot.toCartesianCoords().scalarMultiply(-0.4); - vel.set(1, -vel.get(1)); - - const pos = this.pos - .add(vel.scalarMultiply(2)) - .add(new Vector3D(this.dim).scalarMultiply(0.5)); - - console.log("Firing fireball", this, pos, vel); - - const ball = new Projectile({ - uid: "fireball-" + Math.random().toString().slice(2), - pos: pos.data as IDim, - vel: vel.data as IDim, - }); - ball.vel = vel; - - game.addEntity(ball); - - this.fire.count = this.fire.coolDown; - } -} diff --git a/lib/engine/entities/player/playerActions.ts b/lib/engine/entities/player/playerActions.ts deleted file mode 100644 index b5970d7..0000000 --- a/lib/engine/entities/player/playerActions.ts +++ /dev/null @@ -1,255 +0,0 @@ -// Player actions are an API that lets you controll a player -// The player should know nothing about these. - -import { BlockType } from "@craft/rust-world"; -import { Direction, Game, IDim, Vector3D } from "../../index.js"; -import { MessageDto, MessageHolder } from "../../messageHelpers.js"; -import CubeHelpers from "../cube.js"; -import { Player } from "./player.js"; - -export enum PlayerActionType { - Jump = "jump", - PlaceBlock = "placeBlock", - RemoveBlock = "removeBlock", - ToggleCreative = "toggleCreative", - Move = "move", - Rotate = "rotate", - SetPos = "setPlayerPos", - BeltLeft = "playerBeltLeft", - BeltRight = "playerBeltRight", - SetBeltIndex = "playerSetBeltIndex", - PlaceDebugBlock = "placeDebugBlock", -} - -interface BasePlayerAction { - playerUid: string; -} - -export interface PlayerActionData - extends Record { - [PlayerActionType.Rotate]: { - playerUid: string; - playerRot: IDim; - }; - [PlayerActionType.Move]: { - playerUid: string; - playerRot: IDim; - directions: Direction[]; - }; - [PlayerActionType.SetBeltIndex]: { - playerUid: string; - index: number; - }; - [PlayerActionType.BeltLeft]: { - playerUid: string; - }; - [PlayerActionType.BeltRight]: { - playerUid: string; - }; - [PlayerActionType.Jump]: { - playerUid: string; - }; - [PlayerActionType.SetPos]: { - playerUid: string; - pos: IDim; - }; - [PlayerActionType.PlaceBlock]: { - playerUid: string; - playerPos: IDim; - playerRot: IDim; - }; - [PlayerActionType.RemoveBlock]: { - playerUid: string; - playerPos: IDim; - playerRot: IDim; - }; - [PlayerActionType.PlaceDebugBlock]: { - playerUid: string; - }; -} - -export type PlayerActionDto = MessageDto; - -export class PlayerAction extends MessageHolder< - PlayerActionType, - PlayerActionData -> { - static make(type: T, data: PlayerActionData[T]) { - return new PlayerAction(type, data); - } -} - -export class PlayerActionService { - constructor(private game: Game) {} - - private playerActions = new Map< - string, - Array<(action: PlayerAction) => void> - >(); - - addActionListener( - playerId: string, - listener: (action: PlayerAction) => void - ) { - this.playerActions.set(playerId, [ - ...(this.playerActions.get(playerId) || []), - listener, - ]); - } - - performAction(action: PlayerAction) { - const playerId = action.data.playerUid; - const player = this.game.entities.tryGet(playerId); - - if (!player) { - console.log("Player not found", playerId); - return; - } - - if (!(player instanceof Player)) { - console.log("Entity is not a player", player); - return; - } - - handlePlayerAction(this.game, player, action); - - const listeners = this.playerActions.get(playerId); - if (!listeners) { - return; - } - - for (const listener of listeners) { - listener(action); - } - } -} - -export abstract class PlayerController { - constructor( - protected playerActionService: PlayerActionService, - protected game: Game, - protected player: Player - ) {} - - jump() { - const jumpAction = PlayerAction.make(PlayerActionType.Jump, { - playerUid: this.player.uid, - }); - - this.playerActionService.performAction(jumpAction); - } - - move(directions: Direction[]) { - const action = PlayerAction.make(PlayerActionType.Move, { - directions: Array.from(directions), - playerUid: this.player.uid, - playerRot: this.player.rot.data as IDim, - }); - - this.playerActionService.performAction(action); - } - - primaryAction() { - const action = PlayerAction.make(PlayerActionType.PlaceBlock, { - playerUid: this.player.uid, - playerPos: this.player.pos.data as IDim, - playerRot: this.player.rot.data as IDim, - }); - - this.playerActionService.performAction(action); - } - - secondaryAction() { - const action = PlayerAction.make(PlayerActionType.RemoveBlock, { - playerUid: this.player.uid, - playerPos: this.player.pos.data as IDim, - playerRot: this.player.rot.data as IDim, - }); - this.playerActionService.performAction(action); - } - - selectBelt(pos: number) { - const action = PlayerAction.make(PlayerActionType.SetBeltIndex, { - playerUid: this.player.uid, - index: pos, - }); - this.playerActionService.performAction(action); - } - - toggleCreative() { - const action = PlayerAction.make(PlayerActionType.ToggleCreative, { - playerUid: this.player.uid, - }); - this.playerActionService.performAction(action); - } -} - -const handlePlayerAction = ( - game: Game, - player: Player, - action: PlayerAction -) => { - // console.log("Handling player action", player, action); - if (action.isType(PlayerActionType.Rotate)) { - const { playerRot } = action.data; - player.rot = new Vector3D(playerRot); - return; - } - - if (action.isType(PlayerActionType.Jump)) { - player.tryJump(); - return; - } - - if (action.isType(PlayerActionType.PlaceBlock)) { - const { playerPos, playerRot } = action.data; - player.pos = new Vector3D(playerPos); - player.rot = new Vector3D(playerRot); - player.doPrimaryAction(game); - return; - } - - if (action.isType(PlayerActionType.RemoveBlock)) { - const { playerPos, playerRot } = action.data; - player.pos = new Vector3D(playerPos); - player.rot = new Vector3D(playerRot); - player.doSecondaryAction(game); - return; - } - - if (action.isType(PlayerActionType.SetPos)) { - const { pos } = action.data; - player.pos = new Vector3D(pos); - return; - } - - if (action.isType(PlayerActionType.Move)) { - const { directions, playerRot } = action.data; - // TODO this might be unnecessary - player.rot = new Vector3D(playerRot); - player.moveDirections = directions; - } - - if (action.isType(PlayerActionType.BeltLeft)) { - player.belt.moveLeft(); - } - - if (action.isType(PlayerActionType.BeltRight)) { - player.belt.moveRight(); - } - - if (action.isType(PlayerActionType.SetBeltIndex)) { - const { index } = action.data; - player.belt.setIndex(index); - } - - if (action.isType(PlayerActionType.PlaceDebugBlock)) { - const pos = player.pos.floor(); - const cube = CubeHelpers.createCube(BlockType.Gold, pos); - game.placeBlock(cube); - } - - if (action.isType(PlayerActionType.ToggleCreative)) { - player.setCreative(!player.creative); - } -}; diff --git a/lib/engine/entities/projectile.ts b/lib/engine/entities/projectile.ts deleted file mode 100644 index be25779..0000000 --- a/lib/engine/entities/projectile.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Game, Vector3D } from "../index.js"; -import { World } from "../world/index.js"; -import { IEntity } from "./entity.js"; -import { IEntityType } from "./entityType.js"; -import { MovableEntity, MovableEntityDto } from "./moveableEntity.js"; - -export interface ProjectileDto extends MovableEntityDto { - type: IEntityType.Projectile; -} - -export class Projectile - extends MovableEntity - implements IEntity -{ - // abstract values - static readonly type = IEntityType.Projectile; - get type() { - return Projectile.type; - } - - gravitable = true; - - getDto(): ProjectileDto { - return { - ...this.baseDto(), - type: Projectile.type, - }; - } - - set(data: Partial): void { - this.baseSet(data); - } - - private life = 1000; - - update(game: Game, world: World, delta: number) { - this.life -= delta; - if (this.life < 0) { - game.removeEntity(this); - return; - } - - const scaledVel = this.vel.scalarMultiply(delta / 16); - const expectedPos = this.pos.add(scaledVel); - const newPos = world.tryMove(this, scaledVel); - this.pos = newPos; - - if (!newPos.equals(expectedPos)) { - const intersectingPoss = world.getIntersectingBlocksWithEntity( - expectedPos, - new Vector3D(this.dim) - ); - if (intersectingPoss.length > 0) { - for (const intersectingPos of intersectingPoss) { - const block = world.getBlockFromWorldPoint(intersectingPos); - if (block) { - game.removeBlock(block); - } - } - game.removeEntity(this); - } - } - } -} diff --git a/lib/engine/entities/spectator.ts b/lib/engine/entities/spectator.ts deleted file mode 100644 index d46b900..0000000 --- a/lib/engine/entities/spectator.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Entity, FaceLocater } from "./entity.js"; -import { IDim } from "../types.js"; -import { Vector3D } from "../utils/vector.js"; - -export class Spectator { - // Entity overrides - pos = new Vector3D([0, 5, 0]); - dim: IDim = [1, 2, 1]; - gravitable = false; - intangible = true; - - constructor() { - // super(); - // this.uid = Random.randomString() - } - - // getActions(): IAction[] { - // const actions: IAction[] = []; - - // const wasdVel = this.getWasdVel(); - // const vertVel = this.getVerticalVel(); - - // const totVel = wasdVel.add(vertVel); - - // if (!totVel.equals(this.vel)) { - // actions.push({ - // type: IActionType.setEntVel, - // setEntVel: { - // vel: totVel.data as IDim, - // uid: this.uid, - // } - // }) - // } - - // return actions; - // } - - update(delta: number) { - // this.baseUpdate(delta) - } - - hit(_entity: Entity, _where: FaceLocater) { - /* NO-OP */ - } -} diff --git a/lib/engine/game-scripts/sandbox-gscript.ts b/lib/engine/game-scripts/sandbox-gscript.ts deleted file mode 100644 index f20ec45..0000000 --- a/lib/engine/game-scripts/sandbox-gscript.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { GameScript } from "../game-script.js"; -import { TerrainGenModule } from "../modules.js"; -import { Vector2D, Vector3D } from "../utils/vector.js"; -import { World } from "../world/world.js"; - -interface Config { - seed: string; - flatWorld: boolean; - infinite: boolean; - loadDistance: number; -} - -// init the terrian gen module and load all chunks around palyer -export class SandboxGScript extends GameScript { - name = "sandbox"; - - public config = { - seed: "", - flatWorld: false, - infinite: false, - loadDistance: 3, - }; - - private terrainGenerator: ReturnType< - typeof TerrainGenModule.getTerrainGenerator - > | null = null; - - async setup(): Promise { - console.log("Setting up sandbox game script"); - // Load the entire world? - await TerrainGenModule.load(); - - this.config = { - seed: this.game.config.seed, - flatWorld: this.game.config.terrain.flatWorld, - infinite: this.game.config.terrain.infiniteGen, - loadDistance: this.game.config.loadDistance, - }; - - this.terrainGenerator = TerrainGenModule.getTerrainGenerator( - Number(this.config.seed), - this.config.flatWorld - ); - - // Load the chunks around the player - } - - setConfig(config: Config): void { - this.config = config; - - // TODO: Update the terrain generator's config - } - - getChunkPosAroundPoint(pos: Vector3D): Vector2D[] { - const centerChunkPos = World.worldPosToChunkPos(pos); - - const chunkIds = []; - const loadDistance = this.config.loadDistance; - - for (let i = -loadDistance; i < loadDistance; i++) { - for (let j = -loadDistance; j < loadDistance; j++) { - const chunkPos = new Vector2D([ - centerChunkPos.get(0) + i, - centerChunkPos.get(1) + j, - ]); - chunkIds.push(chunkPos); - } - } - - return chunkIds; - } - - update(_delta: number): void { - if (this.config.infinite) { - for (const entity of this.game.entities.iterable()) { - const chunkIds = this.getChunkPosAroundPoint(entity.pos); - // console.log("Chunk ids", chunkIds); - chunk: for (const chunkId of chunkIds) { - const isChunkLoaded = this.game.world.hasChunk(chunkId); - if (isChunkLoaded) { - continue chunk; - } - - console.log("Generating chunk around player"); - - const chunk = this.terrainGenerator?.getChunk(chunkId); - - if (!chunk) { - console.log("Failed generating chunk", chunkId); - break; - } - - this.game.upsertChunk(chunk); - - // Only load a single chunk per frame - return; - } - } - } - } -} diff --git a/lib/engine/game.ts b/lib/engine/game.ts deleted file mode 100644 index 8434ac6..0000000 --- a/lib/engine/game.ts +++ /dev/null @@ -1,317 +0,0 @@ -import { Player } from "./entities/player/player.js"; -import { ISerializedWorld, World } from "./world/world.js"; -import { CONFIG, IConfig, setConfig } from "./config.js"; -import { EntityHolder, ISerializedEntities } from "./entities/entityHolder.js"; -import { Random } from "./utils/random.js"; -import { GameActionHandler, GameAction } from "./gameActions.js"; -import { GameStateDiff, GameDiffDto } from "./gameStateDiff.js"; -import CubeHelpers, { Cube } from "./entities/cube.js"; -import { Entity, EntityDto, getChunkId, ISerializedChunk } from "./index.js"; -import { GameScript } from "./game-script.js"; - -export interface ISerializedGame { - name: string; - config: IConfig; - gameId: string; - entities?: ISerializedEntities; - world?: ISerializedWorld; -} - -export interface IGameMetadata { - gameId: string; - name: string; -} - -export type ICreateGameOptions = Pick; - -export type IContructGameOptions = Omit & { - gameId?: string; -}; - -export interface IChunkReader { - getChunk(chunkPos: string): Promise; -} - -export interface IGameSaver { - save(game: Game): Promise; -} - -// Receives client actions from somewhere. -// Generate dirty entities and dirty chunks. -export class Game { - public stateDiff: GameStateDiff; - private gameActionHandler: GameActionHandler; - private gameScripts: GameScript[] = []; - - static make(dto: IContructGameOptions, gameSaver: IGameSaver) { - const world = World.make(dto.world); - const entities = new EntityHolder(dto.entities); - const gameId = dto.gameId || Math.random().toString().slice(2, 10); - return new Game(gameId, dto.name, dto.config, entities, world, gameSaver); - } - - constructor( - public gameId: string, - public name: string, - public config: IConfig, - public entities: EntityHolder, - public world: World, - private gameSaver: IGameSaver - ) { - Random.setSeed(this.config.seed); - this.stateDiff = new GameStateDiff(this); - this.gameActionHandler = new GameActionHandler(this); - - setConfig({ - ...CONFIG, - ...this.config, - }); - } - - public serialize(): ISerializedGame { - return { - config: CONFIG, - entities: this.entities.serialize(), - world: this.world.serialize(), - gameId: this.gameId, - name: this.name, - }; - } - - public addGameScript( - script: new (game: Game, ...args: Args) => T, - ...args: Args - ): T { - const s = new script(this, ...args); - this.gameScripts.push(s); - return s; - } - - public getGameScript( - script: new (game: Game, ...args: Args) => T - ): T { - for (const s of this.gameScripts) { - if (s instanceof script) { - return s; - } - } - - throw new Error("Script not found"); - } - - public getScriptActions(): GameScript[] { - const scriptsWithActions = []; - for (const s of this.gameScripts) { - if (s.actions || s.config) { - scriptsWithActions.push(s); - } - } - return scriptsWithActions; - } - - public async setupScripts() { - for (const script of this.gameScripts) { - await script.setup?.(); - } - } - - // This could maybe be a game script - public startTimer() { - let lastTime = 0; - const update = () => { - const now = Date.now(); - const diff = now - lastTime; - lastTime = now; - - // Idk if this is still needed - if (diff > 100) { - console.log("Skipping update, time diff is too large", diff); - return; - } - this.update(diff); - }; - - setInterval(update, 1000 / 40); - } - - public update(delta: number) { - this.entities.update(this, this.world, delta); - - for (const script of this.gameScripts) { - script.update?.(delta); - } - - for (const script of this.gameScripts) { - script.onGameStateDiff?.(this.stateDiff); - } - - this.stateDiff.clear(); - } - - /** This happens on a fast loop. Mark things that change as dirty */ - public handleAction(action: GameAction) { - this.gameActionHandler.handle(action); - for (const script of this.gameScripts) { - script.onGameAction?.(action); - } - } - - /** Currently only sent by server. Will quickly update the state of the game */ - public handleStateDiff(stateDiff: GameDiffDto) { - // Might not have to do this because the updating below will append the updates - this.stateDiff.appendDto(stateDiff); - - console.log("Handling State Diff", stateDiff); - if (stateDiff.chunks.update) { - const updates = stateDiff.chunks.update; - for (const update of updates) { - this.upsertChunk(update, { updateState: false }); - } - } - - if (stateDiff.entities?.add) { - const adds = stateDiff.entities.add; - for (const add of adds) { - const ent = this.entities.createEntity(add); - this.addEntity(ent, { updateState: false }); - } - } - - if (stateDiff.entities.update) { - const updates = stateDiff.entities.update; - for (const update of updates) { - this.updateEntity(update, { updateState: false }); - } - } - - if (stateDiff.entities.remove) { - const removes = stateDiff.entities.remove; - for (const removeId of removes) { - this.removeEntity(this.entities.get(removeId), { updateState: false }); - } - } - } - - upsertChunk( - chunk: ISerializedChunk, - opts: { updateState: boolean } = { updateState: true } - ) { - console.log("Game: Upserting chunk", chunk, opts); - - const chunkId = getChunkId(chunk); - - this.world.updateChunk(chunk); - if (opts.updateState) { - this.stateDiff.updateChunk(chunkId); - } - - for (const script of this.gameScripts) { - script.onChunkUpdate?.(chunkId); - } - } - - placeBlock( - cube: Cube, - opts: { updateState: boolean } = { updateState: true } - ) { - console.log("Game: Adding block", cube); - - // Check if an entity is in the way - // Soon we will move this to rust - for (const entity of this.entities.iterable()) { - if (CubeHelpers.isPointInsideOfCube(cube, entity.pos)) { - console.log("Not adding block, entity in the way"); - return; - } - } - - const updatedChunks = this.world.addBlock(cube); - if (opts.updateState) { - for (const chunkId of updatedChunks) { - this.stateDiff.updateChunk(chunkId); - for (const script of this.gameScripts) { - script.onChunkUpdate?.(chunkId); - } - } - } - } - - removeBlock( - cube: Cube, - opts: { updateState: boolean } = { updateState: true } - ) { - console.log("Game: Removing block", cube); - const updatedChunks = this.world.removeBlock(cube.pos); - if (opts.updateState) { - for (const chunkId of updatedChunks) { - this.stateDiff.updateChunk(chunkId); - for (const script of this.gameScripts) { - script.onChunkUpdate?.(chunkId); - } - } - } - } - - addPlayer( - uid: string, - opts: { updateState: boolean } = { updateState: true } - ): Player { - console.log("Game: Adding player", uid); - - const player = this.entities.createOrGetPlayer(uid); - if (opts.updateState) { - this.stateDiff.updateEntity(player.uid); - } - for (const script of this.gameScripts) { - script.onNewEntity?.(player); - } - return player; - } - - addEntity( - entity: Entity, - opts: { updateState: boolean } = { updateState: true } - ) { - console.log("Game: Adding entity", entity); - this.entities.add(entity); - - if (opts.updateState) { - this.stateDiff.updateEntity(entity.uid); - } - - for (const script of this.gameScripts) { - script.onNewEntity?.(entity); - } - } - - updateEntity( - entity: EntityDto, - opts: { updateState: boolean } = { updateState: true } - ) { - console.log("Game: Updating entity", entity); - this.entities.updateEntity(entity); - if (opts.updateState) { - this.stateDiff.updateEntity(entity.uid); - } - } - - removeEntity( - entity: Entity, - opts: { updateState: boolean } = { updateState: true } - ) { - console.log("Game: Removing entity", entity); - this.entities.remove(entity.uid); - - if (opts.updateState) { - this.stateDiff.removeEntity(entity.uid); - } - - for (const script of this.gameScripts) { - script.onRemovedEntity?.(entity); - } - } - - async save() { - await this.gameSaver.save(this); - } -} diff --git a/lib/engine/gameActions.ts b/lib/engine/gameActions.ts deleted file mode 100644 index 323d38d..0000000 --- a/lib/engine/gameActions.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Game } from "./game.js"; -import { MessageDto, MessageHolder } from "./messageHelpers.js"; - -export enum GameActionType { - Save = "save", - ChangeName = "changeName", -} - -export interface GameActionData extends Record { - [GameActionType.ChangeName]: { - name: string; - }; - [GameActionType.Save]: undefined; -} - -export type GameActionDto = MessageDto; - -export class GameAction extends MessageHolder { - static create(type: T, data: GameActionData[T]) { - return new GameAction(type, data); - } -} - -export class GameActionHandler { - constructor(private game: Game) {} - - handle(action: GameAction) { - if (action.isType(GameActionType.Save)) { - this.game.save(); - } - } -} diff --git a/lib/engine/gameStateDiff.ts b/lib/engine/gameStateDiff.ts deleted file mode 100644 index fa4c722..0000000 --- a/lib/engine/gameStateDiff.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { EntityDto } from "./entities/entity.js"; -import { Game } from "./game.js"; -import { Vector2D } from "./utils/vector.js"; -import { getChunkId, ISerializedChunk } from "./world/chunk.js"; - -export interface GameDiffDto { - entities: { - add?: EntityDto[]; - update?: EntityDto[]; - remove?: string[]; - }; - chunks: { - update?: ISerializedChunk[]; - }; -} - -export interface IGameStateDiffData { - addEntitiesIds: string[]; - updateEntitiesIds: string[]; - removeEntitiesIds: string[]; - updateChunkIds: string[]; -} - -// Stores information about which entities or chunks are dirty -export class GameStateDiff { - constructor(private game: Game, data?: IGameStateDiffData) { - if (!data) { - return; - } - this.addEntitiesIds = data.addEntitiesIds; - this.updateEntitiesIds = data.updateEntitiesIds; - this.removeEntitiesIds = data.removeEntitiesIds; - this.updateChunkIds = data.updateChunkIds; - } - - private addEntitiesIds: string[] = []; - private updateEntitiesIds: string[] = []; - private removeEntitiesIds: string[] = []; - private updateChunkIds: string[] = []; - - public hasData(): boolean { - return ( - this.addEntitiesIds.length > 0 || - this.updateEntitiesIds.length > 0 || - this.removeEntitiesIds.length > 0 || - this.updateChunkIds.length > 0 - ); - } - - public addEntity(entityId: string) { - this.addEntitiesIds.push(entityId); - } - - public removeEntity(entityId: string) { - this.removeEntitiesIds.push(entityId); - } - - public updateEntity(entityId: string) { - this.updateEntitiesIds.push(entityId); - } - - public updateChunk(chunkId: string) { - this.updateChunkIds.push(chunkId); - } - - public getDirtyChunks(): ReadonlyArray { - return this.updateChunkIds; - } - - public getNewEntities(): ReadonlyArray { - return this.addEntitiesIds; - } - - public getUpdatedEntities(): ReadonlyArray { - return this.updateEntitiesIds; - } - - public getRemovedEntities(): ReadonlyArray { - return this.removeEntitiesIds; - } - - public clear() { - this.addEntitiesIds = []; - this.updateEntitiesIds = []; - this.removeEntitiesIds = []; - this.updateChunkIds = []; - } - - public get(): GameDiffDto { - const diff: GameDiffDto = { - entities: {}, - chunks: {}, - }; - - if (this.addEntitiesIds.length > 0) { - diff.entities.add = this.addEntitiesIds - .map((id) => this.game.entities.get(id)) - .map((entity) => entity.getDto()); - } - - if (this.removeEntitiesIds.length > 0) { - diff.entities.remove = this.removeEntitiesIds; - } - - if (this.updateEntitiesIds.length > 0) { - diff.entities.update = this.updateEntitiesIds - .map((id) => this.game.entities.get(id)) - .map((entity) => entity.getDto()); - } - - if (this.updateChunkIds.length > 0) { - diff.chunks.update = this.updateChunkIds.map((id) => - this.game.world.getChunkFromPos(Vector2D.fromIndex(id)) - ); - } - - return diff; - } - - private serialize(): IGameStateDiffData { - return { - addEntitiesIds: this.addEntitiesIds, - updateEntitiesIds: this.updateEntitiesIds, - removeEntitiesIds: this.removeEntitiesIds, - updateChunkIds: this.updateChunkIds, - }; - } - - public copy(): GameStateDiff { - return new GameStateDiff(this.game, this.serialize()); - } - - public append(diff: GameStateDiff) { - this.addEntitiesIds = this.addEntitiesIds.concat(diff.getNewEntities()); - this.updateEntitiesIds = this.updateEntitiesIds.concat( - diff.getUpdatedEntities() - ); - this.removeEntitiesIds = this.removeEntitiesIds.concat( - diff.getRemovedEntities() - ); - this.updateChunkIds = this.updateChunkIds.concat(diff.getDirtyChunks()); - } - - public appendDto(dto: GameDiffDto) { - this.addEntitiesIds.push(...(dto.entities.add?.map((e) => e.uid) || [])); - this.updateChunkIds.push( - ...(dto.chunks.update?.map((c) => getChunkId(c)) || []) - ); - this.removeEntitiesIds.push(...(dto.entities.remove || [])); - this.updateEntitiesIds.push( - ...(dto.entities.update?.map((e) => e.uid) || []) - ); - } -} diff --git a/lib/engine/index.ts b/lib/engine/index.ts deleted file mode 100644 index c0e7627..0000000 --- a/lib/engine/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -export * from "./controllers/controller.js"; -export * from "./controllers/emptyController.js"; -export * from "./game-script.js"; -export * from "./gameActions.js"; -export * from "./gameStateDiff.js"; -export * from "./blockdata.js"; -export * from "./camera.js"; -export * from "./config.js"; -export * from "./game.js"; -export * from "./gameActions.js"; -export * from "./game-scripts/sandbox-gscript.js"; -export * from "./types.js"; -export * from "./world/index.js"; -export * from "./utils/vector.js"; -export * from "./utils/face.js"; -export * from "./utils/random.js"; -export * from "./utils.js"; -export * from "./entities/cube.js"; -export * from "./entities/entity.js"; -export * from "./entities/entityHolder.js"; -export * from "./entities/entityType.js"; -export * from "./entities/entityController.js"; -export * from "./entities/moveableEntity.js"; -export * from "./entities/player/player.js"; -export * from "./entities/player/playerActions.js"; -export * from "./entities/projectile.js"; -export * from "./entities/spectator.js"; -export { WorldModule, TerrainGenModule } from "./modules.js"; diff --git a/lib/engine/item.ts b/lib/engine/item.ts deleted file mode 100644 index 24b5df0..0000000 --- a/lib/engine/item.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { BlockType } from "@craft/rust-world"; - -export enum ThrowableItem { - Fireball = "fireball", -} - -export type Item = BlockType | ThrowableItem; diff --git a/lib/engine/modules.ts b/lib/engine/modules.ts deleted file mode 100644 index 0fe8d50..0000000 --- a/lib/engine/modules.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as WorldWasm from "@craft/rust-world"; -import * as TerrainGenWasm from "@craft/terrain-gen"; -import { Vector2D } from "./utils/vector.js"; -import { - IChunkReader, - ISerializedChunk, - ISerializedWorld, - World, -} from "./index.js"; -export * as WorldModuleTypes from "@craft/rust-world"; - -async function loadWasmModule(module: any, name = "") { - console.log("Loading Wasm Module: ", name); - const loadedModule = module.default ? await module.default : await module; - console.log(`Loaded Wasm Module: ${name} 🎉`); - return loadedModule; -} - -// Wrapper class for world logic -class WorldModuleClass { - private _module: typeof WorldWasm | null = null; - - private get module() { - if (!this._module) { - throw new Error("Module not loaded"); - } - return this._module; - } - - async load(): Promise { - if (this._module) return; - this._module = await loadWasmModule(WorldWasm, "World"); - } - - public createWorld(data?: ISerializedWorld) { - console.log("Creating wasm world"); - const wasmWorld = WorldModule.module.World.new_wasm(); - const world = new World(wasmWorld, data); - return world; - } -} - -export const WorldModule = new WorldModuleClass(); - -class TerrainGenModuleClass { - private _module: typeof TerrainGenWasm | null = null; - - private get module() { - if (!this._module) { - throw new Error("Terrain gen module not loaded"); - } - return this._module; - } - - public async load(): Promise { - if (this._module) return; - this._module = await loadWasmModule(TerrainGenWasm, "TerrainGen"); - } - - getTerrainGenerator(seed: number, flatWorld: boolean) { - const terrainGenerator = new this.module.TerrainGenerator(seed, flatWorld); - - return { - getChunk: (chunkPos: Vector2D) => { - console.log("Generating Chunk", chunkPos); - const chunk = terrainGenerator - .get_chunk(chunkPos.get(0), chunkPos.get(1)) - .serialize(); - return chunk as unknown as ISerializedChunk; - }, - }; - } -} - -export const TerrainGenModule = new TerrainGenModuleClass(); diff --git a/lib/engine/src/api-types.ts b/lib/engine/src/api-types.ts new file mode 100644 index 0000000..ef4553b --- /dev/null +++ b/lib/engine/src/api-types.ts @@ -0,0 +1,78 @@ +import { Entity, GameDiff, Player } from "@craft/rust-world"; +import { ISerializedAction } from "./serialize.js"; + +export interface MessageDto< + MESSAGE extends string, + DATA extends Record +> { + readonly type: MESSAGE; + readonly data: DATA[MESSAGE]; +} + +export class MessageHolder> { + constructor(public type: T, public data: DATA[T]) {} + + getDto() { + return { + type: this.type, + data: this.data, + }; + } + + isType(type: U): this is MessageHolder { + return type === this.type; + } +} + +export enum ISocketMessageType { + // from client + joinWorld = "joinWorld", + + // from server + failedToJoin = "failedToJoin", + welcome = "welcome", + gameDiff = "gameDiff", + newPlayer = "newPlayer", + + // from both + actions = "actions", +} + +export interface WelcomeMessage { + uid: number; + entities: Entity[]; +} + +export interface SocketMessageData extends Record { + [ISocketMessageType.joinWorld]: { + gameId: string; + myUid: number; + }; + [ISocketMessageType.failedToJoin]: void; + [ISocketMessageType.actions]: ISerializedAction; + [ISocketMessageType.gameDiff]: GameDiff; + [ISocketMessageType.welcome]: WelcomeMessage; + [ISocketMessageType.newPlayer]: Player; +} + +export type SocketMessageDto = MessageDto< + ISocketMessageType, + SocketMessageData +>; + +export class SocketMessage extends MessageHolder< + ISocketMessageType, + SocketMessageData +> { + static make( + type: T, + data: SocketMessageData[T] + ) { + return new SocketMessage(type, data); + } +} + +export interface IApiGameMetadata { + gameId: string; + name: string; +} diff --git a/lib/engine/blockdata.ts b/lib/engine/src/blockdata.ts similarity index 100% rename from lib/engine/blockdata.ts rename to lib/engine/src/blockdata.ts diff --git a/lib/engine/src/camera.ts b/lib/engine/src/camera.ts new file mode 100644 index 0000000..344a8e9 --- /dev/null +++ b/lib/engine/src/camera.ts @@ -0,0 +1,68 @@ +import { Vector3D } from "./vector.js"; +import { Player } from "@craft/rust-world"; + +export type Camera = { + // (x, y, z) + pos: Vector3D; + // (dist, theta: [0, 2pi], phi: [0, pi]) + rot: Vector3D; +}; + +const getPlayerOffset = (player: Player) => { + const dim = player.dim; + return new Vector3D([dim.x / 2, dim.y * (9 / 10), dim.z / 2]); +}; + +export const makeCameraForPlayer = (player: Player) => { + const pos = new Vector3D([player.pos.x, player.pos.y, player.pos.z]); + const rot = new Vector3D([0, player.rot.phi, player.rot.theta]); + const adjustedRot = rot.add(new Vector3D([0, 0, 0])); + return { + pos: pos.add(getPlayerOffset(player)), + rot: adjustedRot, + }; +}; + +export const makeThirdPersonBackCamera = (player: Player, dist = 6) => { + const rot = new Vector3D([0, player.rot.phi, player.rot.theta]); + const player_pos = new Vector3D([player.pos.x, player.pos.y, player.pos.z]); + + const pos = rot + .add(new Vector3D([dist, 0, 0])) + .toCartesianCoords() + .multiply(new Vector3D([1, -1, 1])) + .add(getPlayerOffset(player)) + .add(player_pos); + return { + pos, + rot, + }; +}; + +export const makeThirdPersonFrontCamera = (player: Player, dist = 6) => { + const player_rot = new Vector3D([0, player.rot.phi, player.rot.theta]); + const player_pos = new Vector3D([player.pos.x, player.pos.y, player.pos.z]); + + const rot = player_rot.add(new Vector3D([0, Math.PI, 0])); + const pos = player_rot + .add(new Vector3D([dist, Math.PI, 0])) + .toCartesianCoords() + .multiply(new Vector3D([1, -1, 1])) + .add(getPlayerOffset(player)) + .add(player_pos); + + return { + pos, + rot, + }; +}; + +export const makeXRCamera = (player: Player): Camera => { + const player_pos = new Vector3D([player.pos.x, player.pos.y, player.pos.z]); + const pos = getPlayerOffset(player).add(player_pos); + const rot = new Vector3D([0, player.rot.phi, player.rot.theta]); + return { + pos, + rot, + }; +}; diff --git a/lib/engine/game-script.ts b/lib/engine/src/game-script.ts similarity index 56% rename from lib/engine/game-script.ts rename to lib/engine/src/game-script.ts index 1b49a3b..60e9b00 100644 --- a/lib/engine/game-script.ts +++ b/lib/engine/src/game-script.ts @@ -1,6 +1,4 @@ -import { Game } from "./game.js"; -import { GameAction } from "./gameActions.js"; -import { Entity, GameStateDiff } from "./index.js"; +import { Game } from "@craft/rust-world"; export type GameScriptConfig = Record | undefined; @@ -21,13 +19,13 @@ export abstract class GameScript< // Called for every game loop update?(delta: number): void; - onGameAction?(action: GameAction): void; + // onGameAction?(action: GameAction): void; - onGameStateDiff?(stateDiff: GameStateDiff): void; + // onGameStateDiff?(stateDiff: GameStateDiff): void; - onNewEntity?(entity: Entity): void; + // onNewEntity?(entity: Entity): void; - onRemovedEntity?(entity: Entity): void; + // onRemovedEntity?(entity: Entity): void; - onChunkUpdate?(chunkId: string): void; + // onChunkUpdate?(chunkId: number): void; } diff --git a/lib/engine/src/index.ts b/lib/engine/src/index.ts new file mode 100644 index 0000000..4e5015b --- /dev/null +++ b/lib/engine/src/index.ts @@ -0,0 +1,8 @@ +export * from "./camera.js"; +export * from "./vector.js"; +export * from "./serialize.js"; +export * from "./playerActions.js"; +export * from "./utils.js"; +export * from "./blockdata.js"; +export * from "./api-types.js"; +export * from "./game-script.js"; diff --git a/lib/engine/messageHelpers.ts b/lib/engine/src/messageHelpers.ts similarity index 100% rename from lib/engine/messageHelpers.ts rename to lib/engine/src/messageHelpers.ts diff --git a/lib/engine/src/playerActions.ts b/lib/engine/src/playerActions.ts new file mode 100644 index 0000000..80e57ca --- /dev/null +++ b/lib/engine/src/playerActions.ts @@ -0,0 +1,116 @@ +import { + Direction, + EntityActionDto, + Game, + JumpAction, + MoveAction, + RotateAction, + SecondaryBeltAction, + SelectItemAction, + SphericalRotation, + TeleportAction, + UsePrimaryItemAction, +} from "@craft/rust-world"; +export abstract class PlayerController { + private _pendingRotation: SphericalRotation | null = null; + + constructor( + protected game: Game, + protected handleAction: (action: EntityActionDto) => void, + protected playerId: number + ) {} + + jump() { + const action = JumpAction.make_wasm(this.playerId); + this.handleAction(action); + } + + rotate(x: number, y: number) { + if (!this._pendingRotation) { + const player = this.game.getEntityAsPlayer(this.playerId); + if (!player) return; + this._pendingRotation = player.rot; + } + const rotDiff = SphericalRotation.new_wasm(x, y); + this._pendingRotation = this._pendingRotation.add(rotDiff); + // Create a copy for the action since make_wasm consumes the WASM object + const rotCopy = SphericalRotation.new_wasm( + this._pendingRotation.theta, + this._pendingRotation.phi + ); + const action = RotateAction.make_wasm(this.playerId, rotCopy); + this.handleAction(action); + } + + /** Call once per frame to reset frame-local state like the rotation accumulator. */ + resetFrame() { + this._pendingRotation = null; + } + + move(direction: Direction | "None") { + let action: EntityActionDto; + if (direction === "None") { + action = MoveAction.make_wasm(this.playerId, undefined); + } else { + action = MoveAction.make_wasm(this.playerId, direction); + } + this.handleAction(action); + } + + beltRight() { + const player = this.game.getEntityAsPlayer(this.playerId); + if (!player) { + return; + } + const index = player.belt.selected_item; + if (index === 9) { + return; + } + const action = SelectItemAction.make_wasm(this.playerId, index + 1); + this.handleAction(action); + } + + beltLeft() { + const player = this.game.getEntityAsPlayer(this.playerId); + if (!player) { + return; + } + const index = player.belt.selected_item; + if (index === 0) { + return; + } + const action = SelectItemAction.make_wasm(this.playerId, index - 1); + this.handleAction(action); + } + + selectBelt(pos: number) { + const action = SelectItemAction.make_wasm(this.playerId, pos); + this.handleAction(action); + } + + debugBlock() { + // TO-DO + } + + primaryAction() { + const action = UsePrimaryItemAction.make_wasm(this.playerId); + this.handleAction(action); + } + + secondaryAction() { + const action = SecondaryBeltAction.make_wasm(this.playerId); + this.handleAction(action); + } + + teleport(x: number, y: number, z: number) { + const action = TeleportAction.make_wasm(this.playerId, x, y, z); + this.handleAction(action); + } + + toggleCreative() { + // const action = PlayerAction.make(PlayerActionType.ToggleCreative, { + // playerUid: this.player.uid, + // }); + // this.playerActionService.performAction(action); + } +} diff --git a/lib/engine/src/serialize.ts b/lib/engine/src/serialize.ts new file mode 100644 index 0000000..e8ab1b8 --- /dev/null +++ b/lib/engine/src/serialize.ts @@ -0,0 +1,101 @@ +import { + World, + Game, + Entities, + BlockType, + GameScripts, + ChunkFetcher, +} from "@craft/rust-world"; + +const log = (...args: any[]) => { + console.log(`[${new Date().toISOString()}] serialize.ts: `, ...args); +}; + +export interface ISerializedAction { + entity_id: number; + name: string; + data: any; +} + +export interface IServerGameMetadata { + gameId: string; + name: string; + isRunning: boolean; + onlinePlayers: number; +} + +export interface ISerializedChunkFetcher { + type: string; + json: any; +} + +export interface ISerializedScript { + scripts: Array<{ + config: string; + name: string; + }>; +} + +export interface ISerializedChunk { + position: { + x: number; + y: number; + }; + blocks: BlockType[]; + block_data: ("None" | { Image: string })[]; +} + +type ISerializedChunkHolder = ISerializedChunk[]; + +export interface ISerializedWorld { + chunks: ISerializedChunkHolder; +} + +export interface SerializedEntity { + id: number; + name: string; + components: [string, string][]; // [typeName, jsonValue] +} + +export interface SerializedEntities { + entities: SerializedEntity[]; +} + +export interface ISerializedGame { + gameId: string; + name: string; + entities: Entities; + world: World; + scripts: ISerializedScript; + chunkFetcher: ISerializedChunkFetcher; +} + +export const deserializeGame = (serializedGame: ISerializedGame): Game => { + const start = performance.now(); + const world = World.deserialize_wasm(serializedGame.world); + const entityHolder = Entities.deserialize(serializedGame.entities); + const scripts = GameScripts.fromJs(serializedGame.scripts); + const chunkFetcher = ChunkFetcher.deserialize(serializedGame.chunkFetcher); + const game = Game.build( + serializedGame.gameId, + serializedGame.name, + world, + entityHolder, + scripts, + chunkFetcher + ); + const end = performance.now(); + log("Deserialized game in", end - start, "ms"); + return game; +}; + +export const serializeGame = (game: Game): ISerializedGame => { + return { + gameId: game.id, + name: game.name, + entities: game.serializeEntities(), + world: game.world.serialize_wasm(), + chunkFetcher: game.serializeChunkFetcher(), + scripts: game.getScriptsJs(), + }; +}; diff --git a/lib/engine/utils.ts b/lib/engine/src/utils.ts similarity index 98% rename from lib/engine/utils.ts rename to lib/engine/src/utils.ts index c41d556..ab9c73a 100644 --- a/lib/engine/utils.ts +++ b/lib/engine/src/utils.ts @@ -1,4 +1,4 @@ -import { IDim } from "./types.js"; +export type IDim = [number, number, number]; export function roundToNPlaces(num: number, n: number) { return Math.round((num + Number.EPSILON) * 10 ** n) / 10 ** n; diff --git a/lib/engine/utils/vector.ts b/lib/engine/src/vector.ts similarity index 87% rename from lib/engine/utils/vector.ts rename to lib/engine/src/vector.ts index a0254f2..833974c 100644 --- a/lib/engine/utils/vector.ts +++ b/lib/engine/src/vector.ts @@ -1,45 +1,6 @@ type IDim = [number, number, number]; - -// type VectorIndex = bigint; export type VectorIndex = string; -export enum Direction { - Forwards = 0, - Backwards = 1, - Left = 2, - Right = 3, - Up = 4, - Down = 5, -} - -export const getDirectionFromString = (dir: string): Direction => { - switch (dir) { - case "Up": - return Direction.Up; - case "Down": - return Direction.Down; - case "West": - return Direction.Left; - case "East": - return Direction.Right; - case "North": - return Direction.Forwards; - case "South": - return Direction.Backwards; - default: - throw new Error(`Invalid direction: ${dir}`); - } -}; - -export const ALL_DIRECTIONS = [ - Direction.Forwards, - Direction.Backwards, - Direction.Left, - Direction.Right, - Direction.Up, - Direction.Down, -]; - export class Vector { static xVectors = [ [1, 0, 1], @@ -354,24 +315,6 @@ export class Vector3D extends Vector<[number, number, number]> { return new Vector3D(ords); } - static fromDirection(direction: Direction): Vector3D { - console.log("From direction", direction); - switch (direction) { - case Direction.Forwards: - return new Vector3D([0, 0, 1]); - case Direction.Backwards: - return new Vector3D([0, 0, -1]); - case Direction.Right: - return new Vector3D([1, 0, 0]); - case Direction.Left: - return new Vector3D([-1, 0, 0]); - case Direction.Up: - return new Vector3D([0, 1, 0]); - case Direction.Down: - return new Vector3D([0, -1, 0]); - } - } - toIndex(): VectorIndex { // const part1 = BigInt(this.data[0]) << (32n + 8n); // 32 bits // const part2 = BigInt(this.data[1]) << (32n); // 8 bits diff --git a/lib/engine/tsconfig.json b/lib/engine/tsconfig.json index 55a70d3..25e5168 100644 --- a/lib/engine/tsconfig.json +++ b/lib/engine/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", + "rootDir": "./src", "composite": true, "skipLibCheck": true, "module": "NodeNext" }, "exclude": ["dist/**"], - "include": ["./**/*.ts"] + "include": ["src/**/*.ts"] } diff --git a/lib/engine/tsconfig.tsbuildinfo b/lib/engine/tsconfig.tsbuildinfo new file mode 100644 index 0000000..ba97cf9 --- /dev/null +++ b/lib/engine/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../world/pkg/world.d.ts","./src/serialize.ts","./src/api-types.ts","./src/blockdata.ts","./src/vector.ts","./src/camera.ts","./src/game-script.ts","./src/playerActions.ts","./src/utils.ts","./src/index.ts","./src/messageHelpers.ts","../../node_modules/@babel/types/lib/index.d.ts","../../node_modules/@types/babel__generator/index.d.ts","../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../node_modules/@types/babel__template/index.d.ts","../../node_modules/@types/babel__traverse/index.d.ts","../../node_modules/@types/babel__core/index.d.ts","../../node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/@types/node/compatibility/index.d.ts","../../node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/buffer/index.d.ts","../../node_modules/undici-types/header.d.ts","../../node_modules/undici-types/readable.d.ts","../../node_modules/undici-types/file.d.ts","../../node_modules/undici-types/fetch.d.ts","../../node_modules/undici-types/formdata.d.ts","../../node_modules/undici-types/connector.d.ts","../../node_modules/undici-types/client.d.ts","../../node_modules/undici-types/errors.d.ts","../../node_modules/undici-types/dispatcher.d.ts","../../node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/undici-types/global-origin.d.ts","../../node_modules/undici-types/pool-stats.d.ts","../../node_modules/undici-types/pool.d.ts","../../node_modules/undici-types/handlers.d.ts","../../node_modules/undici-types/balanced-pool.d.ts","../../node_modules/undici-types/agent.d.ts","../../node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/undici-types/mock-agent.d.ts","../../node_modules/undici-types/mock-client.d.ts","../../node_modules/undici-types/mock-pool.d.ts","../../node_modules/undici-types/mock-errors.d.ts","../../node_modules/undici-types/proxy-agent.d.ts","../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/undici-types/retry-handler.d.ts","../../node_modules/undici-types/retry-agent.d.ts","../../node_modules/undici-types/api.d.ts","../../node_modules/undici-types/interceptors.d.ts","../../node_modules/undici-types/util.d.ts","../../node_modules/undici-types/cookies.d.ts","../../node_modules/undici-types/patch.d.ts","../../node_modules/undici-types/websocket.d.ts","../../node_modules/undici-types/eventsource.d.ts","../../node_modules/undici-types/filereader.d.ts","../../node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/undici-types/content-type.d.ts","../../node_modules/undici-types/cache.d.ts","../../node_modules/undici-types/index.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/dom-events.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/readline/promises.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/sea.d.ts","../../node_modules/@types/node/sqlite.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/index.d.ts","../../node_modules/@types/connect/index.d.ts","../../node_modules/@types/body-parser/index.d.ts","../../node_modules/@types/cors/index.d.ts","../../node_modules/@types/estree/index.d.ts","../../node_modules/@types/mime/index.d.ts","../../node_modules/@types/send/index.d.ts","../../node_modules/@types/qs/index.d.ts","../../node_modules/@types/range-parser/index.d.ts","../../node_modules/@types/express-serve-static-core/index.d.ts","../../node_modules/@types/http-errors/index.d.ts","../../node_modules/@types/serve-static/index.d.ts","../../node_modules/@types/express/index.d.ts","../../node_modules/@types/gl-matrix/index.d.ts","../../node_modules/@types/json-schema/index.d.ts","../../node_modules/@types/keyv/index.d.ts","../../node_modules/@types/prop-types/index.d.ts","../../node_modules/@types/react/global.d.ts","../../node_modules/csstype/index.d.ts","../../node_modules/@types/react/index.d.ts","../../node_modules/@types/react-dom/index.d.ts","../../node_modules/@types/responselike/index.d.ts","../../node_modules/@types/seedrandom/index.d.ts","../../node_modules/@types/semver/classes/semver.d.ts","../../node_modules/@types/semver/functions/parse.d.ts","../../node_modules/@types/semver/functions/valid.d.ts","../../node_modules/@types/semver/functions/clean.d.ts","../../node_modules/@types/semver/functions/inc.d.ts","../../node_modules/@types/semver/functions/diff.d.ts","../../node_modules/@types/semver/functions/major.d.ts","../../node_modules/@types/semver/functions/minor.d.ts","../../node_modules/@types/semver/functions/patch.d.ts","../../node_modules/@types/semver/functions/prerelease.d.ts","../../node_modules/@types/semver/functions/compare.d.ts","../../node_modules/@types/semver/functions/rcompare.d.ts","../../node_modules/@types/semver/functions/compare-loose.d.ts","../../node_modules/@types/semver/functions/compare-build.d.ts","../../node_modules/@types/semver/functions/sort.d.ts","../../node_modules/@types/semver/functions/rsort.d.ts","../../node_modules/@types/semver/functions/gt.d.ts","../../node_modules/@types/semver/functions/lt.d.ts","../../node_modules/@types/semver/functions/eq.d.ts","../../node_modules/@types/semver/functions/neq.d.ts","../../node_modules/@types/semver/functions/gte.d.ts","../../node_modules/@types/semver/functions/lte.d.ts","../../node_modules/@types/semver/functions/cmp.d.ts","../../node_modules/@types/semver/functions/coerce.d.ts","../../node_modules/@types/semver/classes/comparator.d.ts","../../node_modules/@types/semver/classes/range.d.ts","../../node_modules/@types/semver/functions/satisfies.d.ts","../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../node_modules/@types/semver/ranges/min-version.d.ts","../../node_modules/@types/semver/ranges/valid.d.ts","../../node_modules/@types/semver/ranges/outside.d.ts","../../node_modules/@types/semver/ranges/gtr.d.ts","../../node_modules/@types/semver/ranges/ltr.d.ts","../../node_modules/@types/semver/ranges/intersects.d.ts","../../node_modules/@types/semver/ranges/simplify.d.ts","../../node_modules/@types/semver/ranges/subset.d.ts","../../node_modules/@types/semver/internals/identifiers.d.ts","../../node_modules/@types/semver/index.d.ts","../../node_modules/@types/webidl-conversions/index.d.ts","../../node_modules/@types/webxr/index.d.ts","../../node_modules/@types/whatwg-url/index.d.ts","../../node_modules/@types/ws/index.d.ts"],"fileIdsList":[[47,48,69,112],[47,69,112],[47,51,69,112],[48,49,50,51,52,53,54,55,69,112],[69,112],[58,69,112],[58,59,60,61,62,69,112],[58,60,69,112],[69,112,127,162,163],[69,112,127,162],[69,112,124,127,162,168,169,170],[69,112,164,169,171,173],[69,112,175],[69,112,124,162],[69,109,112],[69,111,112],[112],[69,112,117,147],[69,112,113,118,124,125,132,144,155],[69,112,113,114,124,132],[64,65,66,69,112],[69,112,115,156],[69,112,116,117,125,133],[69,112,117,144,152],[69,112,118,120,124,132],[69,111,112,119],[69,112,120,121],[69,112,124],[69,112,122,124],[69,111,112,124],[69,112,124,125,126,144,155],[69,112,124,125,126,139,144,147],[69,107,112,160],[69,107,112,120,124,127,132,144,155],[69,112,124,125,127,128,132,144,152,155],[69,112,127,129,144,152,155],[67,68,69,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161],[69,112,124,130],[69,112,131,155],[69,112,120,124,132,144],[69,112,133],[69,112,134],[69,111,112,135],[69,109,110,111,112,113,114,115,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161],[69,112,137],[69,112,138],[69,112,124,139,140],[69,112,139,141,156,158],[69,112,124,144,145,147],[69,112,146,147],[69,112,144,145],[69,112,147],[69,112,148],[69,109,112,144],[69,112,124,150,151],[69,112,150,151],[69,112,117,132,144,152],[69,112,153],[69,112,132,154],[69,112,127,138,155],[69,112,117,156],[69,112,144,157],[69,112,131,158],[69,112,159],[69,112,117,124,126,135,144,155,158,160],[69,112,144,161],[69,112,181],[69,112,178,179,180],[69,112,127,144,162],[69,112,185,224],[69,112,185,209,224],[69,112,224],[69,112,185],[69,112,185,210,224],[69,112,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223],[69,112,210,224],[69,112,125,144,162,167],[69,112,127,162,168,172],[69,112,124,127,129,132,144,152,155,161,162],[69,79,83,112,155],[69,79,112,144,155],[69,74,112],[69,76,79,112,152,155],[69,112,132,152],[69,112,162],[69,74,112,162],[69,76,79,112,132,155],[69,71,72,75,78,112,124,144,155],[69,79,86,112],[69,71,77,112],[69,79,100,101,112],[69,75,79,112,147,155,162],[69,100,112,162],[69,73,74,112,162],[69,79,112],[69,73,74,75,76,77,78,79,80,81,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,101,102,103,104,105,106,112],[69,79,94,112],[69,79,86,87,112],[69,77,79,87,88,112],[69,78,112],[69,71,74,79,112],[69,79,83,87,88,112],[69,83,112],[69,77,79,82,112,155],[69,71,76,79,86,112],[69,112,144],[69,74,79,100,112,160,162]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"092c2bfe125ce69dbb1223c85d68d4d2397d7d8411867b5cc03cec902c233763","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"9fd4e97e73911659479e2455b8c1b1272c0216562663188cad2a5c386d25fd28","impliedFormat":99},{"version":"bc6c7c642b4c2e84953a03d9306323aaaae80daf6d650d7538485ee2f73b07ec","signature":"47962d0680fe4cd6e645f7231c0774b0f4041faa4a6d5d522dcf3871876a27fa","impliedFormat":99},{"version":"4c89c2497dffcd2dec6a8ee8075719545163214393166c6c5542de09dc76ee4f","signature":"0177e6117f562265fea03e7e70f5b408861dc2281c099fcce07768a655bd8687","impliedFormat":99},{"version":"cc5b076ac0f6607279e70a6254873d7929f52254d6d854bfbc95f7e21379eacd","signature":"723c8f01f59ba76ea8057364b30eb863584157893a3a06ddd381a5579efce21d","impliedFormat":99},{"version":"dbce1a180bdd50d83d0c1a5c07fd5bc0870c6afa4dfec57ba8d7153837715f46","signature":"30f017d88514e0806b293981b753975158585001d76e8f0c37bba5fdee67e3a0","impliedFormat":99},{"version":"be0742a712314d1ff5abbf6e0ab8f19820b4004c8eb2881c7db28a7d71695cbc","signature":"e85731236253a48ecc7417c332254f495e829ee1a59b6359cb7732f87b153318","impliedFormat":99},{"version":"1e20cfe580515334f0b432b26673699222b566ab627585b1197fd0f19dd696ef","signature":"1ba770ec9fa3f3f9d2a7c8d26b95208327927d7fe6046e65574d2fcff854ce17","impliedFormat":99},{"version":"b034e4fc88c160a686ae4c986e76dbf9a04befc677fd2df3523f2fd3453c3b3c","signature":"70c9425cbaefd481bd76d8c806b68664348a0da2b46aac154155f0d9fe06cd50","impliedFormat":99},{"version":"368f662f9b34973be10e9230ec1041f8b4b30310887cfe6755afd0ff968674d6","signature":"1b6256fb93bee06b9b07cd2c6554c9135ce2fd1f8a9472c328dfb62ff7817348","impliedFormat":99},{"version":"29b5d606da6db9a01664e84fae53674ced22682a02e96e24b9e1b6497049ed6d","impliedFormat":99},{"version":"c377b02fff54ab51cd49d83cd77dedd57146f5a0dbb31ecde57694fd1ee1e48a","signature":"7d5fb2c9812ddb34bd3bcf2c4cbf3a61807603aa4b6a47d88fb7d747ae571253","impliedFormat":99},{"version":"d88b3dc8b7055665059ea06ffafce9467fc4bdfa7cb2d7a6f4262556bb482b0d","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"32ddc6ad753ae79571bbf28cebff7a383bf7f562ac5ef5d25c94ef7f71609d49","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"81df92841a7a12d551fcbc7e4e83dbb7d54e0c73f33a82162d13e9ae89700079","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"030e350db2525514580ed054f712ffb22d273e6bc7eddc1bb7eda1e0ba5d395e","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"a79e62f1e20467e11a904399b8b18b18c0c6eea6b50c1168bf215356d5bebfaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"d802f0e6b5188646d307f070d83512e8eb94651858de8a82d1e47f60fb6da4e2","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"88d9a77d2abc23a7d26625dd6dae5b57199a8693b85c9819355651c9d9bab90f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a38efe83ff77c34e0f418a806a01ca3910c02ee7d64212a59d59bca6c2c38fa1","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"3fe4022ba1e738034e38ad9afacbf0f1f16b458ed516326f5bf9e4a31e9be1dc","impliedFormat":1},{"version":"a957197054b074bcdf5555d26286e8461680c7c878040d0f4e2d5509a7524944","affectsGlobalScope":true,"impliedFormat":1},{"version":"4314c7a11517e221f7296b46547dbc4df047115b182f544d072bdccffa57fc72","impliedFormat":1},{"version":"e9b97d69510658d2f4199b7d384326b7c4053b9e6645f5c19e1c2a54ede427fc","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"f478f6f5902dc144c0d6d7bdc919c5177cac4d17a8ca8653c2daf6d7dc94317f","affectsGlobalScope":true,"impliedFormat":1},{"version":"19d5f8d3930e9f99aa2c36258bf95abbe5adf7e889e6181872d1cdba7c9a7dd5","impliedFormat":1},{"version":"b200675fd112ffef97c166d0341fb33f6e29e9f27660adde7868e95c5bc98beb","impliedFormat":1},{"version":"a6bf63d17324010ca1fbf0389cab83f93389bb0b9a01dc8a346d092f65b3605f","impliedFormat":1},{"version":"e009777bef4b023a999b2e5b9a136ff2cde37dc3f77c744a02840f05b18be8ff","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true,"impliedFormat":1},{"version":"88bc59b32d0d5b4e5d9632ac38edea23454057e643684c3c0b94511296f2998c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a0a1dda070290b92da5a50113b73ecc4dd6bcbffad66e3c86503d483eafbadcf","impliedFormat":1},{"version":"59dcad36c4549175a25998f6a8b33c1df8e18df9c12ebad1dfb25af13fd4b1ce","impliedFormat":1},{"version":"206a70e72af3e24688397b81304358526ce70d020e4c2606c4acfd1fa1e81fb2","impliedFormat":1},{"version":"3f3edb8e44e3b9df3b7ca3219ab539710b6a7f4fe16bd884d441af207e03cd57","impliedFormat":1},{"version":"528b62e4272e3ddfb50e8eed9e359dedea0a4d171c3eb8f337f4892aac37b24b","impliedFormat":1},{"version":"d71535813e39c23baa113bc4a29a0e187b87d1105ccc8c5a6ebaca38d9a9bff2","impliedFormat":1},{"version":"8cf7e92bdb2862c2d28ba4535c43dc599cfbc0025db5ed9973d9b708dcbe3d98","affectsGlobalScope":true,"impliedFormat":1},{"version":"f72bc8fe16da67e4e3268599295797b202b95e54bd215a03f97e925dd1502a36","impliedFormat":1},{"version":"b1b6ee0d012aeebe11d776a155d8979730440082797695fc8e2a5c326285678f","impliedFormat":1},{"version":"45875bcae57270aeb3ebc73a5e3fb4c7b9d91d6b045f107c1d8513c28ece71c0","impliedFormat":1},{"version":"1dc73f8854e5c4506131c4d95b3a6c24d0c80336d3758e95110f4c7b5cb16397","affectsGlobalScope":true,"impliedFormat":1},{"version":"636302a00dfd1f9fe6e8e91e4e9350c6518dcc8d51a474e4fc3a9ba07135100b","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"8145e07aad6da5f23f2fcd8c8e4c5c13fb26ee986a79d03b0829b8fce152d8b2","impliedFormat":1},{"version":"e1120271ebbc9952fdc7b2dd3e145560e52e06956345e6fdf91d70ca4886464f","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"e1ce1d622f1e561f6cdf246372ead3bbc07ce0342024d0e9c7caf3136f712698","impliedFormat":1},{"version":"c878f74b6d10b267f6075c51ac1d8becd15b4aa6a58f79c0cfe3b24908357f60","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"125d792ec6c0c0f657d758055c494301cc5fdb327d9d9d5960b3f129aff76093","impliedFormat":1},{"version":"27e4532aaaa1665d0dd19023321e4dc12a35a741d6b8e1ca3517fcc2544e0efe","affectsGlobalScope":true,"impliedFormat":1},{"version":"2754d8221d77c7b382096651925eb476f1066b3348da4b73fe71ced7801edada","impliedFormat":1},{"version":"8c2ad42d5d1a2e8e6112625767f8794d9537f1247907378543106f7ba6c7df90","affectsGlobalScope":true,"impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"98ffdf93dfdd206516971d28e3e473f417a5cfd41172e46b4ce45008f640588e","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"7d6ff413e198d25639f9f01f16673e7df4e4bd2875a42455afd4ecc02ef156da","affectsGlobalScope":true,"impliedFormat":1},{"version":"12e8ce658dd17662d82fb0509d2057afc5e6ee30369a2e9e0957eff725b1f11d","affectsGlobalScope":true,"impliedFormat":1},{"version":"74736930d108365d7bbe740c7154706ccfb1b2a3855a897963ab3e5c07ecbf19","impliedFormat":1},{"version":"858f999b3e4a45a4e74766d43030941466460bf8768361d254234d5870480a53","impliedFormat":1},{"version":"ac5ed35e649cdd8143131964336ab9076937fa91802ec760b3ea63b59175c10a","impliedFormat":1},{"version":"63b05afa6121657f25e99e1519596b0826cda026f09372c9100dfe21417f4bd6","affectsGlobalScope":true,"impliedFormat":1},{"version":"3797dd6f4ea3dc15f356f8cdd3128bfa18122213b38a80d6c1f05d8e13cbdad8","impliedFormat":1},{"version":"ad90122e1cb599b3bc06a11710eb5489101be678f2920f2322b0ac3e195af78d","impliedFormat":1},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"cc0d0b339f31ce0ab3b7a5b714d8e578ce698f1e13d7f8c60bfb766baeb1d35c","impliedFormat":1},{"version":"25be1eb939c9c63242c7a45446edb20c40541da967f43f1aa6a00ed53c0552db","impliedFormat":1},{"version":"e2b48abff5a8adc6bb1cd13a702b9ef05e6045a98e7cfa95a8779b53b6d0e69d","impliedFormat":1},{"version":"d3f2d715f57df3f04bf7b16dde01dec10366f64fce44503c92b8f78f614c1769","impliedFormat":1},{"version":"b78cd10245a90e27e62d0558564f5d9a16576294eee724a59ae21b91f9269e4a","impliedFormat":1},{"version":"baac9896d29bcc55391d769e408ff400d61273d832dd500f21de766205255acb","impliedFormat":1},{"version":"2f5747b1508ccf83fad0c251ba1e5da2f5a30b78b09ffa1cfaf633045160afed","impliedFormat":1},{"version":"a45c25e77c911c1f2a04cade78f6f42b4d7d896a3882d4e226efd3a3fcd5f2c4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b71c603a539078a5e3a039b20f2b0a0d1708967530cf97dec8850a9ca45baa2b","impliedFormat":1},{"version":"0e13570a7e86c6d83dd92e81758a930f63747483e2cd34ef36fcdb47d1f9726a","impliedFormat":1},{"version":"5c45abf1e13e4463eacfd5dedda06855da8748a6a6cb3334f582b52e219acc04","impliedFormat":1},{"version":"4a0f0317476f6801c0e19b8ba226ccaf5970a598e6439e6facd1054b59b078e0","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"fec943fdb3275eb6e006b35e04a8e2e99e9adf3f4b969ddf15315ac7575a93e4","impliedFormat":1},{"version":"65ff5a0aefd7817a03c1ad04fee85c9cdd3ec415cc3c9efec85d8008d4d5e4ee","impliedFormat":1},{"version":"eb5b19b86227ace1d29ea4cf81387279d04bb34051e944bc53df69f58914b788","affectsGlobalScope":true,"impliedFormat":1},{"version":"8a8eb4ebffd85e589a1cc7c178e291626c359543403d58c9cd22b81fab5b1fb9","impliedFormat":1},{"version":"69b76e74a56b52e89f3400cbd99a9e2a67f4a4f7b6d0b07dff2c637ac514b3e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"17ed71200119e86ccef2d96b73b02ce8854b76ad6bd21b5021d4269bec527b5f","impliedFormat":1},{"version":"8718fa41d7cf4aa91de4e8f164c90f88e0bf343aa92a1b9b725a9c675c64e16b","impliedFormat":1},{"version":"bb5d24e66d38263b1bda38d0f9b7a72aa2a9de2f7dfd840132a2e372bffd95d8","impliedFormat":1},{"version":"cf3d384d082b933d987c4e2fe7bfb8710adfd9dc8155190056ed6695a25a559e","impliedFormat":1},{"version":"9871b7ee672bc16c78833bdab3052615834b08375cb144e4d2cba74473f4a589","impliedFormat":1},{"version":"c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","impliedFormat":1},{"version":"8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","impliedFormat":1},{"version":"86c73f2ee1752bac8eeeece234fd05dfcf0637a4fbd8032e4f5f43102faa8eec","impliedFormat":1},{"version":"42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","impliedFormat":1},{"version":"ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","impliedFormat":1},{"version":"83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","impliedFormat":1},{"version":"1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","impliedFormat":1},{"version":"0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","impliedFormat":1},{"version":"cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","impliedFormat":1},{"version":"c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","impliedFormat":1},{"version":"f4e9bf9103191ef3b3612d3ec0044ca4044ca5be27711fe648ada06fad4bcc85","impliedFormat":1},{"version":"0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","impliedFormat":1},{"version":"7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","impliedFormat":1},{"version":"bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","impliedFormat":1},{"version":"52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","impliedFormat":1},{"version":"770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","impliedFormat":1},{"version":"d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","impliedFormat":1},{"version":"799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","impliedFormat":1},{"version":"2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","impliedFormat":1},{"version":"9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","impliedFormat":1},{"version":"397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","impliedFormat":1},{"version":"a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","impliedFormat":1},{"version":"a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","impliedFormat":1},{"version":"c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","impliedFormat":1},{"version":"4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","impliedFormat":1},{"version":"f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","impliedFormat":1},{"version":"cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","impliedFormat":1},{"version":"b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","impliedFormat":1},{"version":"c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","impliedFormat":1},{"version":"14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","impliedFormat":1},{"version":"a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","impliedFormat":1},{"version":"f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","impliedFormat":1},{"version":"3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","impliedFormat":1},{"version":"662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","impliedFormat":1},{"version":"c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","impliedFormat":1},{"version":"2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","impliedFormat":1},{"version":"34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","impliedFormat":1},{"version":"844ab83672160ca57a2a2ea46da4c64200d8c18d4ebb2087819649cad099ff0e","impliedFormat":1},{"version":"f2f23fe34b735887db1d5597714ae37a6ffae530cafd6908c9d79d485667c956","impliedFormat":1},{"version":"6414851ace6758f45d36688d409766f48c6edba5ebbd1a925b1b30e992412b9d","impliedFormat":1},{"version":"5bba0e6cd8375fd37047e99a080d1bd9a808c95ecb7f3043e3adc125196f6607","impliedFormat":1},{"version":"1ba59c8bbeed2cb75b239bb12041582fa3e8ef32f8d0bd0ec802e38442d3f317","impliedFormat":1}],"root":[[48,57]],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"esModuleInterop":true,"module":199,"noImplicitAny":true,"outDir":"./dist","preserveConstEnums":true,"removeComments":true,"rootDir":"./src","skipLibCheck":true,"sourceMap":true,"strict":true,"strictNullChecks":true,"target":99},"referencedMap":[[49,1],[50,2],[52,3],[53,2],[56,4],[57,5],[54,2],[48,2],[55,5],[51,5],[47,5],[60,6],[58,5],[63,7],[59,6],[61,8],[62,6],[164,9],[163,10],[165,10],[166,5],[171,11],[174,12],[175,13],[172,5],[176,5],[177,14],[167,5],[109,15],[110,15],[111,16],[69,17],[112,18],[113,19],[114,20],[64,5],[67,21],[65,5],[66,5],[115,22],[116,23],[117,24],[118,25],[119,26],[120,27],[121,27],[123,28],[122,29],[124,30],[125,31],[126,32],[108,33],[68,5],[127,34],[128,35],[129,36],[162,37],[130,38],[131,39],[132,40],[133,41],[134,42],[135,43],[136,44],[137,45],[138,46],[139,47],[140,47],[141,48],[142,5],[143,5],[144,49],[146,50],[145,51],[147,52],[148,53],[149,54],[150,55],[151,56],[152,57],[153,58],[154,59],[155,60],[156,61],[157,62],[158,63],[159,64],[160,65],[161,66],[178,5],[169,5],[170,5],[182,67],[179,5],[181,68],[183,69],[184,5],[209,70],[210,71],[185,72],[188,72],[207,70],[208,70],[198,70],[197,73],[195,70],[190,70],[203,70],[201,70],[205,70],[189,70],[202,70],[206,70],[191,70],[192,70],[204,70],[186,70],[193,70],[194,70],[196,70],[200,70],[211,74],[199,70],[187,70],[224,75],[223,5],[218,74],[220,76],[219,74],[212,74],[213,74],[215,74],[217,74],[221,76],[222,76],[214,76],[216,76],[168,77],[173,78],[225,5],[226,5],[227,5],[228,79],[70,5],[180,5],[45,5],[46,5],[8,5],[10,5],[9,5],[2,5],[11,5],[12,5],[13,5],[14,5],[15,5],[16,5],[17,5],[18,5],[3,5],[19,5],[20,5],[4,5],[21,5],[25,5],[22,5],[23,5],[24,5],[26,5],[27,5],[28,5],[5,5],[29,5],[30,5],[31,5],[32,5],[6,5],[36,5],[33,5],[34,5],[35,5],[37,5],[7,5],[38,5],[43,5],[44,5],[39,5],[40,5],[41,5],[42,5],[1,5],[86,80],[96,81],[85,80],[106,82],[77,83],[76,84],[105,85],[99,86],[104,87],[79,88],[93,89],[78,90],[102,91],[74,92],[73,85],[103,93],[75,94],[80,95],[81,5],[84,95],[71,5],[107,96],[97,97],[88,98],[89,99],[91,100],[87,101],[90,102],[100,85],[82,103],[83,104],[92,105],[72,106],[95,97],[94,95],[98,5],[101,107]],"latestChangedDtsFile":"./dist/playerActions.d.ts","version":"5.8.3"} \ No newline at end of file diff --git a/lib/engine/types.ts b/lib/engine/types.ts deleted file mode 100644 index e028cbb..0000000 --- a/lib/engine/types.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { IConfig } from "./config.js"; -import { EntityDto } from "./entities/entity.js"; -import { PlayerActionDto } from "./entities/player/playerActions.js"; -import { - Game, - IContructGameOptions, - IGameMetadata, - ISerializedGame, -} from "./game.js"; -import { GameActionDto } from "./gameActions.js"; -import { GameDiffDto } from "./gameStateDiff.js"; -import { MessageDto, MessageHolder } from "./messageHelpers.js"; -import { ISerializedChunk } from "./world/chunk.js"; - -export type IDim = [number, number, number]; - -// Defs -// There are actions and state changes -// Actions are sent to the server to be converted to state changes that are then sent to the clients -// Servers can only just send state changes to the clients without any actions (An entity spawned, a timer went off) - -export enum StateUpdateType { - AddEntity, - UpdateEntity, - RemoveEntity, - UpdateChunk, -} - -export interface IAddEntityStateUpdate { - action: StateUpdateType.AddEntity; - ent: EntityDto; -} - -export interface IUpdateEntityStateUpdate { - action: StateUpdateType.UpdateEntity; - ent: Partial; -} - -export interface IEntityRemoveStateUpdate { - action: StateUpdateType.RemoveEntity; - uid: string; -} - -export interface IChunkUpdateStateUpdate { - action: StateUpdateType.UpdateChunk; - chunk: ISerializedChunk; -} - -export type StateUpdate = - | IAddEntityStateUpdate - | IUpdateEntityStateUpdate - | IEntityRemoveStateUpdate - | IChunkUpdateStateUpdate; - -export interface IGamesService { - createGame(options: IContructGameOptions): Promise; - getGame(gameId: string): Promise; - getAllGames(): Promise; - saveGame(game: Game): Promise; - deleteGame(gameId: string): Promise; -} - -export enum ISocketMessageType { - // from client - getChunk = "getChunk", // server sends setChunk - newWorld = "newWorld", // server sends welcome - saveWorld = "saveWorld", - // this could be for joining an existing world or starting up an old one - joinWorld = "joinWorld", // server sends welcome or worldNotFound - // from server - welcome = "welcome", - worldNotFound = "worldNotFound", - gameDiff = "gameDiff", - setChunk = "setChunk", - newPlayer = "newPlayer", - playerLeave = "playerLeave", - // both - actions = "actions", - playerActions = "playerActions", -} - -export interface SocketMessageData extends Record { - [ISocketMessageType.joinWorld]: { - myUid: string; - worldId: string; - }; - [ISocketMessageType.newWorld]: { - myUid: string; - config: IConfig; - name: string; - }; - [ISocketMessageType.saveWorld]: { - worldId: string; - }; - [ISocketMessageType.getChunk]: { - pos: string; - }; - [ISocketMessageType.welcome]: ISocketWelcomePayload; - [ISocketMessageType.worldNotFound]: {}; - [ISocketMessageType.setChunk]: { - pos: string; - data: ISerializedChunk; - }; - [ISocketMessageType.newPlayer]: { - uid: string; - }; - [ISocketMessageType.playerLeave]: { - uid: string; - }; - [ISocketMessageType.gameDiff]: GameDiffDto; - [ISocketMessageType.actions]: GameActionDto; - [ISocketMessageType.playerActions]: PlayerActionDto; -} - -export interface ISocketWelcomePayload { - uid: string; - game: ISerializedGame; -} - -export type SocketMessageDto = MessageDto< - ISocketMessageType, - SocketMessageData ->; - -export class SocketMessage extends MessageHolder< - ISocketMessageType, - SocketMessageData -> { - static make( - type: T, - data: SocketMessageData[T] - ) { - return new SocketMessage(type, data); - } -} diff --git a/lib/engine/utils/face.ts b/lib/engine/utils/face.ts deleted file mode 100644 index 332a292..0000000 --- a/lib/engine/utils/face.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Vector3D } from "./vector.js"; - -export function getOppositeCubeFace(face: number) { - return face % 2 === 0 ? face + 1 : face - 1; -} - -export function faceVectorToFaceNumber(vector: Vector3D): number { - const index = (Vector3D.unitVectors - .map((val, index) => [val, index] as [Vector3D, number]) - .find(([val, _index]) => val.equals(vector)) ?? [-1, -1])[1]; - - if (index === -1) { - throw new Error("Couldn't find face vector"); - } - - return index; -} - -export function faceNumberToFaceVector(faceIndex: number): Vector3D { - return Vector3D.unitVectors[faceIndex]; -} diff --git a/lib/engine/utils/random.ts b/lib/engine/utils/random.ts deleted file mode 100644 index ffae915..0000000 --- a/lib/engine/utils/random.ts +++ /dev/null @@ -1,48 +0,0 @@ -import seedrandom from "seedrandom"; -import random from "random"; -import { CONFIG } from "../config.js"; -import simplexNoise from "simplex-noise"; - -class RandomClass { - private _rndNoise: simplexNoise = new simplexNoise(); - private jagFactor = CONFIG.terrain.jagFactor; - - setSeed(seed: string) { - console.log("Setting random seed", seed); - random.use(seedrandom(seed)); - this._rndNoise = new simplexNoise(seed); - } - - // returns random number from [0,1] - noise(x: number, y: number) { - return this.customNoise(x, y, this.jagFactor); - } - - customNoise(x: number, y: number, jagFactor: number) { - const num = this._rndNoise.noise2D(x / jagFactor, y / jagFactor); - return (num + 1) / 2; - } - - randomNum() { - return random.float(0, 1); - } - - randomInt(min: number, max: number) { - return random.int(min, max); - } - - randomFloat(min: number, max: number) { - return random.float(min, max); - } - - randomString() { - return random.float(0, 1).toString(); - } - - randomElement(data: T[]) { - const rndIndex = this.randomInt(0, data.length - 1); - return data[rndIndex]; - } -} - -export const Random = new RandomClass(); diff --git a/lib/engine/world/chunk.ts b/lib/engine/world/chunk.ts deleted file mode 100644 index a5c5c66..0000000 --- a/lib/engine/world/chunk.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Cube } from "../entities/cube.js"; -import { Direction, Vector2D } from "../utils/vector.js"; -import { BlockType } from "@craft/rust-world"; -export interface ILookingAtData { - cube: Cube; - face: Direction; - dist: number; -} - -export interface ISerializedChunk { - position: { - x: number; - y: number; - }; - blocks: BlockType[]; - block_data: ("None" | { Image: string })[]; -} - -export const getChunkId = (serChunk: ISerializedChunk) => { - const vec = new Vector2D([serChunk.position.x, serChunk.position.y]); - return vec.toIndex(); -}; - -export type ISerializedVisibleFaces = Array<{ - world_pos: { x: 0; y: 0; z: 0 }; - faces: [boolean, boolean, boolean, boolean, boolean, boolean]; -}>; diff --git a/lib/engine/world/chunkMesh.ts b/lib/engine/world/chunkMesh.ts deleted file mode 100644 index 110a7c5..0000000 --- a/lib/engine/world/chunkMesh.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Cube } from "../index.js"; -import { Direction } from "../utils/vector.js"; - -export class ChunkMesh { - constructor( - public mesh: Array<{ block: Cube; faces: Direction[] }>, - public chunkPos: { x: number; y: number } - ) {} -} diff --git a/lib/engine/world/index.ts b/lib/engine/world/index.ts deleted file mode 100644 index 942f3ff..0000000 --- a/lib/engine/world/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./biome.js"; -export * from "./chunk.js"; -export * from "./terrainGenerator.js"; -export * from "./world.js"; -export * from "./chunkMesh.js"; diff --git a/lib/engine/world/world.ts b/lib/engine/world/world.ts deleted file mode 100644 index 210d8da..0000000 --- a/lib/engine/world/world.ts +++ /dev/null @@ -1,236 +0,0 @@ -import CubeHelpers, { - Cube, - ISerializedCube, - WasmCube, -} from "../entities/cube.js"; -import { ILookingAtData, ISerializedChunk } from "./chunk.js"; -import { Entity } from "../entities/entity.js"; -import { CONFIG } from "../config.js"; -import { - Vector3D, - Vector2D, - Direction, - getDirectionFromString, -} from "../utils/vector.js"; -import { WorldModule, WorldModuleTypes } from "../modules.js"; -import { ChunkMesh } from "./chunkMesh.js"; -import { CameraRay } from "../index.js"; - -type ISerializedChunkHolder = ISerializedChunk[]; - -export interface ISerializedWorld { - chunks: ISerializedChunkHolder; -} - -export class World { - static make(data?: ISerializedWorld): World { - return WorldModule.createWorld(data); - } - - constructor( - public wasmWorld: WorldModuleTypes.World, - data?: ISerializedWorld - ) { - if (data) { - console.log("World: Loading world from data", data); - for (const chunkData of data.chunks) { - this.updateChunk(chunkData); - } - } - } - - serialize(): ISerializedWorld { - const ser = this.wasmWorld.serialize_wasm() as { - chunks: Map; - }; - console.log("Serializing world", ser); - return { - chunks: Array.from(ser.chunks.values()), - }; - } - - static worldPosToChunkPos(pos: Vector3D): Vector2D { - return new Vector2D([ - Math.floor(pos.get(0) / CONFIG.terrain.chunkSize), - Math.floor(pos.get(2) / CONFIG.terrain.chunkSize), - ]); - } - - static chunkPosToWorldPos(pos: Vector2D, center = false): Vector3D { - return new Vector3D([ - pos.get(0) * CONFIG.terrain.chunkSize + - (center ? CONFIG.terrain.chunkSize / 2 : 0), - 0, - pos.get(1) * CONFIG.terrain.chunkSize + - (center ? CONFIG.terrain.chunkSize / 2 : 0), - ]); - } - - static chunkIdToChunkPos(chunkId: string): Vector2D { - const [x, y] = chunkId.split(",").map((s) => parseInt(s)); - return new Vector2D([x, y]); - } - - getChunkFromPos(chunkPos: Vector2D): ISerializedChunk { - console.log("Getting chunk from pos", chunkPos); - const chunk = this.wasmWorld.get_chunk_from_chunk_pos_wasm({ - x: chunkPos.get(0), - y: chunkPos.get(1), - }); - return chunk; - } - - getChunkMesh(chunkPos: Vector2D): ChunkMesh { - const wasmMesh: Array<[WasmCube, { data: Array }]> = - this.wasmWorld.get_chunk_mesh_wasm(chunkPos.toCartIntObj()); - - const betterMesh = wasmMesh.map(([cube, { data }]) => { - const block = CubeHelpers.fromWasmCube(cube); - const faces = data - .map((b, i) => (b ? i : -1)) - .filter((i) => i !== -1) as Direction[]; - return { - block, - faces, - }; - }); - - return new ChunkMesh(betterMesh, chunkPos.toCartIntObj()); - } - - getBlockFromWorldPoint(pos: Vector3D): Cube | null { - const wasmBlock: ISerializedCube = this.wasmWorld.get_block_wasm( - pos.toCartIntObj() - ); - return CubeHelpers.fromWasmCube(wasmBlock); - } - - updateChunk(chunkData: ISerializedChunk) { - const time = performance.now(); - this.wasmWorld.insert_chunk_wasm(chunkData); - const time2 = performance.now(); - console.log(`Upserting chunk took (${time2 - time}ms)`); - } - - hasChunk(chunkPos: Vector2D): boolean { - try { - return this.wasmWorld.is_chunk_loaded_wasm({ - x: chunkPos.get(0), - y: chunkPos.get(1), - }); - } catch (e) { - console.error("Error in hasChunk", chunkPos, e); - throw e; - } - } - - getLoadedChunkIds(): string[] { - const loaded_pos = this.wasmWorld.get_loaded_chunk_pos() as { - x: number; - y: number; - }[]; - - return loaded_pos - .map((p: { x: number; y: number }) => { - return new Vector2D([p.x, p.y]); - }) - .map((p) => p.toIndex()); - } - - tryMove(entity: Entity, vel: Vector3D): Vector3D { - const endPos = { - x: entity.pos.get(0) + vel.get(0), - y: entity.pos.get(1) + vel.get(1), - z: entity.pos.get(2) + vel.get(2), - }; - const ent = { - pos: { - x: entity.pos.get(0), - y: entity.pos.get(1), - z: entity.pos.get(2), - }, - dim: { - x: entity.dim[0], - y: entity.dim[1], - z: entity.dim[2], - }, - }; - const newPos = this.wasmWorld.move_rect3_wasm(ent, endPos); - return new Vector3D([newPos.x, newPos.y, newPos.z]); - } - - getIntersectingBlocksWithEntity(pos: Vector3D, dim: Vector3D): Vector3D[] { - const worldPosList = this.wasmWorld.get_rect3_intersecting_blocks_wasm({ - pos: { - x: pos.get(0), - y: pos.get(1), - z: pos.get(2), - }, - dim: { - x: dim.get(0), - y: dim.get(1), - z: dim.get(2), - }, - }); - - const vecs: Vector3D[] = worldPosList.map( - (pos: { x: number; y: number; z: number }) => - new Vector3D([pos.x, pos.y, pos.z]) - ); - return vecs; - } - - /** - * @returns array of chunk ids that were affected - * */ - addBlock(cube: Cube): string[] { - // console.log("World: Adding block", cube); - const hasChunk = this.hasChunk(World.worldPosToChunkPos(cube.pos)); - if (!hasChunk) { - throw new Error("Trying to place block in unloaded chunk"); - } - const diff: { chunk_ids: string[] } = this.wasmWorld.add_block_wasm({ - block_type: cube.type, - extra_data: "None", - world_pos: { - x: cube.pos.get(0), - y: cube.pos.get(1), - z: cube.pos.get(2), - }, - }); - // console.log("Chunks to updated after adding block: ", diff); - return diff.chunk_ids; - } - - /** - * @returns array of chunk ids that were affected - * */ - removeBlock(cubePos: Vector3D): string[] { - // console.log("Removing block", cubePos); - const diff: { chunk_ids: string[] } = this.wasmWorld.remove_block_wasm( - cubePos.get(0), - cubePos.get(1), - cubePos.get(2) - ); - // console.log("Chunks to updated after removing block: ", diff); - return diff.chunk_ids; - } - - lookingAt(camera: CameraRay): ILookingAtData | null { - const lookingData: { - block: ISerializedCube; - face: string; - distance: number; - } | null = this.wasmWorld.get_pointed_at_block_wasm(camera); - - console.log("Cam looking at ", lookingData, camera); - - if (!lookingData) return null; - - return { - cube: CubeHelpers.fromWasmCube(lookingData.block), - face: getDirectionFromString(lookingData.face), - dist: lookingData.distance, - }; - } -} diff --git a/lib/terrain-gen/Cargo.toml b/lib/terrain-gen/Cargo.toml index 7577a11..38faa5c 100644 --- a/lib/terrain-gen/Cargo.toml +++ b/lib/terrain-gen/Cargo.toml @@ -24,6 +24,7 @@ web-sys = "0.3.64" rand = { version = "0.8.5" } rand_distr = "0.4.3" getrandom = { version = "0.2", features = ["js"] } +serde = "1.0.204" [dev-dependencies] diff --git a/lib/terrain-gen/src/lib.rs b/lib/terrain-gen/src/lib.rs index eba2fea..5635b1e 100644 --- a/lib/terrain-gen/src/lib.rs +++ b/lib/terrain-gen/src/lib.rs @@ -3,6 +3,7 @@ use noise::{NoiseFn, Perlin}; use rand::rngs::StdRng; use rand::SeedableRng; use rand_distr::{Distribution, Uniform}; +use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::*; use world::{ block::{self, BlockType, ChunkBlock}, @@ -101,6 +102,7 @@ impl TreeLocator { blocks.push(WorldBlock { world_pos: pos, block_type: BlockType::Leaf, + extra_data: block::BlockData::None, }); } @@ -111,16 +113,24 @@ impl TreeLocator { pub struct TreeRandomSpreadGenerator { seed: u64, + dist: Uniform, } impl TreeRandomSpreadGenerator { + fn make_from_seed(seed: u64) -> TreeRandomSpreadGenerator { + TreeRandomSpreadGenerator { + seed, + dist: Uniform::new(0, CHUNK_WIDTH), + } + } + + fn get_potential_tree_locations( &self, chunk_pos: ChunkPos, ) -> Box> { let chunk_seed = self.seed + (chunk_pos.x as u64 * 1000) + (chunk_pos.y as u64 * 1000000); let mut rng: StdRng = SeedableRng::seed_from_u64(chunk_seed); - let dist = Uniform::new(0, CHUNK_WIDTH); let mut tree_locations: Vec = Vec::new(); @@ -396,6 +406,95 @@ impl FlatWorldChunkGetter { } } +#[derive(Serialize, Deserialize)] +#[wasm_bindgen] +struct ParkorChunkGetter { + #[wasm_bindgen(skip)] + pub current_blocks: Vec, + + // how far away the blocks are generated from requested chunks + pub load_distance: u8, +} + +#[wasm_bindgen] +impl ParkorChunkGetter { + pub fn new() -> ParkorChunkGetter { + ParkorChunkGetter { + current_blocks: Vec::new(), + load_distance: 4, + } + } + + pub fn get_chunk_wasm(&mut self, chunk_x: i16, chunk_y: i16) -> Chunk { + let chunk_pos = ChunkPos { + x: chunk_x, + y: chunk_y, + }; + self.get_chunk(&chunk_pos) + } +} + +impl ParkorChunkGetter { + pub fn get_next_block(&self) -> WorldBlock { + let current_block = self.current_blocks.last(); + + if let Some(block) = current_block { + let block_pos = block.world_pos; + + // compute the next pos + let next_pos = block_pos + .move_direction(&Direction::North) + .move_direction(&Direction::North); + + WorldBlock { + world_pos: next_pos, + block_type: BlockType::Stone, + extra_data: block::BlockData::None, + } + } else { + // return the first block + WorldBlock { + world_pos: WorldPos::new(0, 0, 0), + block_type: BlockType::Stone, + extra_data: block::BlockData::None, + } + } + } + + fn load_chunk(&mut self, chunk_pos: &ChunkPos) { + // check if there are any blocks in this chunk + let next_block = self.get_next_block(); + + let mut count = 0; + + // keep loading the next block until it isn't load distance away from me + while next_block.world_pos.to_chunk_pos().distance_to(*chunk_pos) as u8 + <= self.load_distance + && count < 10 + { + self.current_blocks.push(next_block); + let next_block = self.get_next_block(); + self.current_blocks.push(next_block); + count += 1; + } + } + + pub fn get_chunk(&mut self, chunk_pos: &ChunkPos) -> Chunk { + let mut chunk = Chunk::new(*chunk_pos); + + self.load_chunk(chunk_pos); + + for block in self.current_blocks.iter() { + let block_chunk_pos = block.world_pos.to_chunk_pos(); + if block_chunk_pos == *chunk_pos { + chunk.add_block(block.to_chunk_block()); + } + } + + chunk + } +} + #[wasm_bindgen] pub struct TerrainGenerator { pub seed: u32, diff --git a/lib/world/Cargo.toml b/lib/world/Cargo.toml index 2d9e22d..dd74f77 100644 --- a/lib/world/Cargo.toml +++ b/lib/world/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Tyler Tracy "] edition = "2018" description = "Logic for a world" -repository = "https://www.github.com" +repository = "https://www.github.com/tylerthecoder/TylerCraft" license = "GPL2" [lib] @@ -14,17 +14,25 @@ crate-type = ["cdylib", "rlib"] default = ["console_error_panic_hook"] [dependencies] -wasm-bindgen = { version = "0.2.92", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.100", features = ["serde-serialize"] } lazy_static = "1.4.0" num = "0.4" js-sys = "0.3.59" serde = { version = "1.0", features = ["derive"] } serde_repr = "0.1" serde-big-array = "0.4.1" -serde-wasm-bindgen = "0.4" +serde-wasm-bindgen = "0.6.5" +serde_json = "1.0.140" +tsify = { version = "0.5.5", features = ["js"] } float-cmp = "0.9.0" phf = { version = "0.11", default-features = false, features = ["macros"] } -web-sys = { version = "0.3.60", features = ["console"] } +web-sys = { version = "0.3.60", features = ["console", "Headers", "Request", "RequestInit", "RequestMode", "Response", "Window"] } +noise = "0.8.2" +rand = { version = "0.8.5" } +rand_distr = "0.4.3" +getrandom = { version = "0.2", features = ["js"] } +uuid = { version = "1.16.0", features = ["v4", "js"] } +rustc-hash = { version = "2.1"} # The `console_error_panic_hook` crate provides better debugging of panics by # logging them with `console.error`. This is great for development, but requires @@ -39,6 +47,8 @@ console_error_panic_hook = { version = "0.1.6", optional = true } # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. wee_alloc = { version = "0.4.5", optional = true } watch = "0.2.3" +once_cell = "1.21.3" +wasm-bindgen-futures = "0.4.51" [dev-dependencies] wasm-bindgen-test = "0.3.34" diff --git a/lib/world/examples/profile_test.rs b/lib/world/examples/profile_test.rs new file mode 100644 index 0000000..b977090 --- /dev/null +++ b/lib/world/examples/profile_test.rs @@ -0,0 +1,24 @@ +use std::time::{Duration, Instant}; + +use world::{chunk::chunk_pos::ChunkPos, terrain_gen::TerrainGenerator, world::World}; + +fn main() { + // This reproduces the profile_chunk_insertion test as a standalone example + let terrain_gen = TerrainGenerator::default(); + + let mut times = Vec::new(); + for _i in 0..500 { + let start_time = Instant::now(); + let mut world = World::default(); + let chunk_pos = ChunkPos::new(0, 0); + let chunk = terrain_gen.get_chunk(chunk_pos.x, chunk_pos.y); + world.insert_chunk(chunk); + times.push(start_time.elapsed()); + } + + println!( + "Average time: {:?}", + times.iter().sum::() / times.len() as u32 + ); + println!("Max time: {:?}", times.iter().max().unwrap()); +} diff --git a/lib/world/flamegraph.svg b/lib/world/flamegraph.svg new file mode 100644 index 0000000..5b61cac --- /dev/null +++ b/lib/world/flamegraph.svg @@ -0,0 +1,491 @@ +Flame Graph Reset ZoomSearch <usize as core::slice::index::SliceIndex<[T]>>::get_unchecked::precondition_check (1,328,969 samples, 10.59%)<usize as core:..[unknown] (501,504 samples, 4.00%)[unk..profile_test::main (2,342,934 samples, 18.67%)profile_test::mainworld::entities::terrain_gen::TerrainGenerator::get_chunk (2,342,934 samples, 18.67%)world::entities::terrain_gen:..world::entities::terrain_gen::BasicChunkGetter::get_chunk (2,342,934 samples, 18.67%)world::entities::terrain_gen:..world::entities::terrain_gen::TreeRandomSpreadGenerator::get_trees (1,149,336 samples, 9.16%)world::entiti..world::entities::terrain_gen::TreeRandomSpreadGenerator::get_tree_locations (1,149,336 samples, 9.16%)world::entiti..world::entities::terrain_gen::TreeRandomSpreadGenerator::get_potential_tree_locations (1,149,336 samples, 9.16%)world::entiti..rand_core::SeedableRng::seed_from_u64 (647,832 samples, 5.16%)rand_c..<rand::rngs::std::StdRng as rand_core::SeedableRng>::from_seed (647,832 samples, 5.16%)<rand:..<rand_chacha::chacha::ChaCha12Rng as rand_core::SeedableRng>::from_seed (647,832 samples, 5.16%)<rand_..<rand_chacha::chacha::ChaCha12Core as rand_core::SeedableRng>::from_seed (647,832 samples, 5.16%)<rand_..rand_chacha::guts::ChaCha::new (647,832 samples, 5.16%)rand_c..rand_chacha::guts::init_chacha (647,832 samples, 5.16%)rand_c..rand_chacha::guts::init_chacha::impl_avx (647,832 samples, 5.16%)rand_c..rand_chacha::guts::init_chacha::fn_impl (647,832 samples, 5.16%)rand_c..core::slice::index::<impl core::ops::index::Index<I> for [T]>::index (647,832 samples, 5.16%)core::..<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::index (647,832 samples, 5.16%)<core:..<core::ops::range::Range<usize> as core::slice::index::SliceIndex<[T]>>::get_unchecked (647,832 samples, 5.16%)<core:..world::entities::terrain_gen::BasicChunkGetter::get_chunk (934,706 samples, 7.45%)world::ent..world::entities::terrain_gen::TreeRandomSpreadGenerator::get_trees (934,706 samples, 7.45%)world::ent..world::entities::terrain_gen::TreeRandomSpreadGenerator::get_tree_locations (934,706 samples, 7.45%)world::ent..world::entities::terrain_gen::TreeRandomSpreadGenerator::get_potential_tree_locations (934,706 samples, 7.45%)world::ent..core::iter::traits::iterator::Iterator::collect (934,706 samples, 7.45%)core::iter..<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (934,706 samples, 7.45%)<alloc::ve..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (934,706 samples, 7.45%)<alloc::ve..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (934,706 samples, 7.45%)<alloc::ve..<core::iter::adapters::take::Take<I> as core::iter::traits::iterator::Iterator>::next (934,706 samples, 7.45%)<core::ite..<rand::distributions::distribution::DistIter<D,R,T> as core::iter::traits::iterator::Iterator>::next (934,706 samples, 7.45%)<rand::dis..<rand::distributions::uniform::Uniform<X> as rand::distributions::distribution::Distribution<X>>::sample (934,706 samples, 7.45%)<rand::dis..<rand::distributions::uniform::UniformInt<u16> as rand::distributions::uniform::UniformSampler>::sample (934,706 samples, 7.45%)<rand::dis..rand::rng::Rng::gen (934,706 samples, 7.45%)rand::rng:..rand::distributions::integer::<impl rand::distributions::distribution::Distribution<u32> for rand::distributions::Standard>::sample (934,706 samples, 7.45%)rand::dist..<&mut R as rand_core::RngCore>::next_u32 (934,706 samples, 7.45%)<&mut R as..<rand::rngs::std::StdRng as rand_core::RngCore>::next_u32 (934,706 samples, 7.45%)<rand::rng..<rand_chacha::chacha::ChaCha12Rng as rand_core::RngCore>::next_u32 (934,706 samples, 7.45%)<rand_chac..<rand_core::block::BlockRng<R> as rand_core::RngCore>::next_u32 (934,706 samples, 7.45%)<rand_core..rand_core::block::BlockRng<R>::generate_and_set (934,706 samples, 7.45%)rand_core:..<rand_chacha::chacha::ChaCha12Core as rand_core::block::BlockRngCore>::generate (934,706 samples, 7.45%)<rand_chac..rand_chacha::guts::ChaCha::refill4 (934,706 samples, 7.45%)rand_chach..rand_chacha::guts::refill_wide (934,706 samples, 7.45%)rand_chach..rand_chacha::guts::refill_wide::impl_avx2 (934,706 samples, 7.45%)rand_chach..rand_chacha::guts::refill_wide::fn_impl (934,706 samples, 7.45%)rand_chach..rand_chacha::guts::refill_wide_impl (934,706 samples, 7.45%)rand_chach..rand_chacha::guts::round (934,706 samples, 7.45%)rand_chach..<ppv_lite86::soft::x2<W,G> as ppv_lite86::types::RotateEachWord32>::rotate_each_word_right16 (934,706 samples, 7.45%)<ppv_lite8..<ppv_lite86::x86_64::sse2::avx2::u32x4x2_avx2<NI> as ppv_lite86::types::RotateEachWord32>::rotate_each_word_right16 (934,706 samples, 7.45%)<ppv_lite8..core::core_arch::x86::avx2::_mm256_shuffle_epi8 (934,706 samples, 7.45%)core::core..core::ptr::drop_in_place<alloc::vec::into_iter::IntoIter<world::direction::Direction>> (501,504 samples, 4.00%)core..<alloc::vec::into_iter::IntoIter<T,A> as core::ops::drop::Drop>::drop (501,504 samples, 4.00%)<all..alloc::vec::into_iter::IntoIter<T,A>::as_raw_mut_slice (501,504 samples, 4.00%)allo..<&mut I as core::iter::traits::exact_size::ExactSizeIterator>::len (501,504 samples, 4.00%)<&mu..core::iter::traits::exact_size::ExactSizeIterator::len (501,504 samples, 4.00%)core..<alloc::vec::into_iter::IntoIter<T,A> as core::iter::traits::iterator::Iterator>::size_hint (501,504 samples, 4.00%)<all..world::chunk::Chunk::get_all_world_blocks_and_dirty (1,596,300 samples, 12.72%)world::chunk::Chunk..world::chunk::Chunk::get_all_world_blocks (1,596,300 samples, 12.72%)world::chunk::Chunk..core::iter::traits::iterator::Iterator::collect (1,596,300 samples, 12.72%)core::iter::traits:..<alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter (1,596,300 samples, 12.72%)<alloc::vec::Vec<T>..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter (1,596,300 samples, 12.72%)<alloc::vec::Vec<T>..<alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter (1,596,300 samples, 12.72%)<alloc::vec::Vec<T>..<alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend (1,596,300 samples, 12.72%)<alloc::vec::Vec<T,..alloc::vec::Vec<T,A>::extend_desugared (1,596,300 samples, 12.72%)alloc::vec::Vec<T,A..<core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::next (1,596,300 samples, 12.72%)<core::iter::adapte..<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1,596,300 samples, 12.72%)<core::iter::adapte..core::iter::traits::iterator::Iterator::find (1,596,300 samples, 12.72%)core::iter::traits:..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::try_fold (1,596,300 samples, 12.72%)<core::iter::adapte..core::iter::traits::iterator::Iterator::try_fold (1,596,300 samples, 12.72%)core::iter::traits:..<core::iter::adapters::enumerate::Enumerate<I> as core::iter::traits::iterator::Iterator>::try_fold::enumerate::_{{closure}} (1,596,300 samples, 12.72%)<core::iter::adapte..core::iter::traits::iterator::Iterator::find::check::_{{closure}} (1,596,300 samples, 12.72%)core::iter::traits:..core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (1,596,300 samples, 12.72%)core::ops::function..world::chunk::Chunk::get_all_world_blocks::_{{closure}} (1,596,300 samples, 12.72%)world::chunk::Chunk..<std::hash::random::DefaultHasher as core::hash::Hasher>::finish (623,223 samples, 4.97%)<std::..<core::hash::sip::SipHasher13 as core::hash::Hasher>::finish (623,223 samples, 4.97%)<core:..<core::hash::sip::Hasher<S> as core::hash::Hasher>::finish (623,223 samples, 4.97%)<core:..<core::hash::sip::Sip13Rounds as core::hash::sip::Sip>::c_rounds (623,223 samples, 4.97%)<core:..core::num::<impl u64>::rotate_left (623,223 samples, 4.97%)core::..world::chunk::chunk_mesh::ChunkMesh::insert (1,611,330 samples, 12.84%)world::chunk::chunk..std::collections::hash::map::HashMap<K,V,S>::insert (1,611,330 samples, 12.84%)std::collections::h..hashbrown::map::HashMap<K,V,S,A>::insert (1,611,330 samples, 12.84%)hashbrown::map::Has..hashbrown::map::make_hash (1,611,330 samples, 12.84%)hashbrown::map::mak..core::hash::BuildHasher::hash_one (1,611,330 samples, 12.84%)core::hash::BuildHa..core::hash::impls::<impl core::hash::Hash for &T>::hash (988,107 samples, 7.88%)core::hash:..core::hash::impls::<impl core::hash::Hash for usize>::hash (988,107 samples, 7.88%)core::hash:..core::hash::Hasher::write_usize (988,107 samples, 7.88%)core::hash:..<std::hash::random::DefaultHasher as core::hash::Hasher>::write (988,107 samples, 7.88%)<std::hash:..<core::hash::sip::SipHasher13 as core::hash::Hasher>::write (988,107 samples, 7.88%)<core::hash..<core::hash::sip::Hasher<S> as core::hash::Hasher>::write (988,107 samples, 7.88%)<core::hash..<core::hash::sip::Sip13Rounds as core::hash::sip::Sip>::c_rounds (988,107 samples, 7.88%)<core::hash..world::components::world_pos::WorldPos::to_inner_chunk_pos (1,502,184 samples, 11.97%)world::components:..world::direction::DirectionVectorExtension::move_direction (478,570 samples, 3.81%)worl..world::vec::Vector3Ops::copy (478,570 samples, 3.81%)worl..all (12,546,611 samples, 100%)profile_test (12,546,611 samples, 100.00%)profile_testworld::world::world_chunk::<impl world::world::World>::insert_chunk (7,438,498 samples, 59.29%)world::world::world_chunk::<impl world::world::World>::insert_chunkworld::world::world_mesh::<impl world::world::World>::update_chunk_mesh (7,438,498 samples, 59.29%)world::world::world_mesh::<impl world::world::World>::update_chunk_meshworld::world::world_block::WorldBlock::get_visible_faces (1,247,106 samples, 9.94%)world::world::..core::iter::traits::iterator::Iterator::collect (1,247,106 samples, 9.94%)core::iter::tr..<world::direction::Directions as core::iter::traits::collect::FromIterator<world::direction::Direction>>::from_iter (1,247,106 samples, 9.94%)<world::direct..<core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::next (1,247,106 samples, 9.94%)<core::iter::a..core::iter::traits::iterator::Iterator::find (1,247,106 samples, 9.94%)core::iter::tr..core::iter::traits::iterator::Iterator::try_fold (1,247,106 samples, 9.94%)core::iter::tr..core::iter::traits::iterator::Iterator::find::check::_{{closure}} (501,504 samples, 4.00%)core..core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut (501,504 samples, 4.00%)core..world::world::world_block::WorldBlock::get_visible_faces::_{{closure}} (501,504 samples, 4.00%)worl..world::world::AdjacentBlocks::get_for_direction (501,504 samples, 4.00%)worl.. \ No newline at end of file diff --git a/lib/world/src/block.rs b/lib/world/src/block.rs index b914a10..b094633 100644 --- a/lib/world/src/block.rs +++ b/lib/world/src/block.rs @@ -1,12 +1,10 @@ use crate::{ - direction::Direction, - positions::{ChunkPos, InnerChunkPos}, + chunk::{chunk_pos::ChunkPos, inner_chunk_pos::InnerChunkPos}, + geometry::direction::Direction, world::world_block::WorldBlock, }; -use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use std::collections::HashMap; use wasm_bindgen::prelude::*; #[wasm_bindgen] @@ -61,7 +59,7 @@ pub enum BlockData { pub mod wasm { use wasm_bindgen::prelude::wasm_bindgen; - use crate::direction::Direction; + use crate::geometry::direction::Direction; #[wasm_bindgen] pub struct ImageData { @@ -102,153 +100,130 @@ impl Default for &BlockMetaData { impl BlockMetaData { pub fn get_for_type(block_type: BlockType) -> &'static BlockMetaData { - BLOCK_DATA.get(&block_type).unwrap_or_default() + let index = block_type as usize; + if index < BLOCK_DATA.len() { + &BLOCK_DATA[index] + } else { + &DEFAULT_BLOCK_DATA + } } } #[wasm_bindgen] impl BlockMetaData { pub fn get_for_type_wasm(block_type: BlockType) -> Option { - BLOCK_DATA.get(&block_type).copied() + let index = block_type as usize; + if index < BLOCK_DATA.len() { + Some(BLOCK_DATA[index]) + } else { + None + } } } -lazy_static! { - static ref BLOCK_DATA: HashMap = { - let mut map: HashMap = HashMap::new(); - map.insert( - BlockType::Void, - BlockMetaData { - gravitable: false, - intangible: true, - shape: BlockShape::Cube, - transparent: true, - fluid: false, - }, - ); - map.insert( - BlockType::Stone, - BlockMetaData { - gravitable: false, - intangible: false, - shape: BlockShape::Cube, - transparent: false, - fluid: false, - }, - ); - map.insert( - BlockType::Image, - BlockMetaData { - gravitable: false, - intangible: false, - shape: BlockShape::Flat, - transparent: true, - fluid: false, - }, - ); - map.insert( - BlockType::Grass, - BlockMetaData { - gravitable: false, - intangible: false, - shape: BlockShape::Cube, - transparent: false, - fluid: false, - }, - ); - map.insert( - BlockType::Wood, - BlockMetaData { - gravitable: false, - intangible: false, - shape: BlockShape::Cube, - fluid: false, - transparent: false, - }, - ); - map.insert( - BlockType::Leaf, - BlockMetaData { - gravitable: false, - intangible: false, - fluid: false, - shape: BlockShape::Cube, - transparent: true, - }, - ); - map.insert( - BlockType::Cloud, - BlockMetaData { - gravitable: false, - intangible: false, - fluid: false, - shape: BlockShape::Cube, - transparent: false, - }, - ); - map.insert( - BlockType::Gold, - BlockMetaData { - gravitable: false, - intangible: false, - fluid: false, - shape: BlockShape::Cube, - transparent: false, - }, - ); - map.insert( - BlockType::RedFlower, - BlockMetaData { - gravitable: false, - intangible: false, - fluid: false, - shape: BlockShape::X, - transparent: true, - }, - ); - map.insert( - BlockType::Water, - BlockMetaData { - gravitable: false, - intangible: true, - fluid: true, - shape: BlockShape::Cube, - transparent: false, - }, - ); - map.insert( - BlockType::RedFlower, - BlockMetaData { - gravitable: false, - intangible: false, - fluid: false, - shape: BlockShape::X, - transparent: true, - }, - ); - - map.insert( - BlockType::Planks, - BlockMetaData { - gravitable: false, - intangible: false, - fluid: false, - shape: BlockShape::Cube, - transparent: false, - }, - ); - - map.insert( - BlockType::Red, - BlockMetaData { - gravitable: false, - intangible: false, - fluid: false, - shape: BlockShape::Cube, - transparent: false, - }, - ); +const DEFAULT_BLOCK_DATA: BlockMetaData = BlockMetaData { + gravitable: false, + intangible: false, + fluid: false, + shape: BlockShape::Cube, + transparent: false, +}; - map - }; -} +const BLOCK_DATA: [BlockMetaData; 12] = [ + // BlockType::Void = 0 + BlockMetaData { + gravitable: false, + intangible: true, + shape: BlockShape::Cube, + transparent: true, + fluid: false, + }, + // BlockType::Stone = 1 + BlockMetaData { + gravitable: false, + intangible: false, + shape: BlockShape::Cube, + transparent: false, + fluid: false, + }, + // BlockType::Wood = 2 + BlockMetaData { + gravitable: false, + intangible: false, + shape: BlockShape::Cube, + fluid: false, + transparent: false, + }, + // BlockType::Leaf = 3 + BlockMetaData { + gravitable: false, + intangible: false, + fluid: false, + shape: BlockShape::Cube, + transparent: true, + }, + // BlockType::Cloud = 4 + BlockMetaData { + gravitable: false, + intangible: false, + fluid: false, + shape: BlockShape::Cube, + transparent: false, + }, + // BlockType::Gold = 5 + BlockMetaData { + gravitable: false, + intangible: false, + fluid: false, + shape: BlockShape::Cube, + transparent: false, + }, + // BlockType::RedFlower = 6 + BlockMetaData { + gravitable: false, + intangible: false, + fluid: false, + shape: BlockShape::X, + transparent: true, + }, + // BlockType::Water = 7 + BlockMetaData { + gravitable: false, + intangible: true, + fluid: true, + shape: BlockShape::Cube, + transparent: false, + }, + // BlockType::Grass = 8 + BlockMetaData { + gravitable: false, + intangible: false, + shape: BlockShape::Cube, + transparent: false, + fluid: false, + }, + // BlockType::Image = 9 + BlockMetaData { + gravitable: false, + intangible: false, + shape: BlockShape::Flat, + transparent: true, + fluid: false, + }, + // BlockType::Planks = 10 + BlockMetaData { + gravitable: false, + intangible: false, + fluid: false, + shape: BlockShape::Cube, + transparent: false, + }, + // BlockType::Red = 11 + BlockMetaData { + gravitable: false, + intangible: false, + fluid: false, + shape: BlockShape::Cube, + transparent: false, + }, +]; diff --git a/lib/world/src/chunk.rs b/lib/world/src/chunk/chunk.rs similarity index 82% rename from lib/world/src/chunk.rs rename to lib/world/src/chunk/chunk.rs index c5e3412..8371051 100644 --- a/lib/world/src/chunk.rs +++ b/lib/world/src/chunk/chunk.rs @@ -1,16 +1,11 @@ use crate::block::{BlockData, BlockType, ChunkBlock}; -use crate::positions::{ChunkPos, InnerChunkPos}; +use crate::chunk::chunk_pos::ChunkPos; +use crate::chunk::inner_chunk_pos::InnerChunkPos; use crate::world::world_block::WorldBlock; -use phf::set; use serde::{Deserialize, Serialize}; use serde_big_array::BigArray; use wasm_bindgen::prelude::*; -mod chunk_duct; -pub mod chunk_mesh; -#[cfg(test)] -mod chunk_unit_tests; - #[wasm_bindgen(typescript_custom_section)] const ITEXT_STYLE: &'static str = r#" interface ITextStyle { @@ -20,7 +15,10 @@ interface ITextStyle { } "#; +pub type ChunkId = u64; + pub const CHUNK_WIDTH: i16 = 16; + pub const CHUNK_HEIGHT: i16 = 64; const CHUNK_MEM_SIZE: usize = (CHUNK_HEIGHT * CHUNK_WIDTH * CHUNK_WIDTH) as usize; @@ -31,7 +29,7 @@ fn default_block_data() -> BlockDataArray { [BlockData::None; CHUNK_MEM_SIZE] } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] #[wasm_bindgen] pub struct Chunk { #[serde(with = "BigArray")] @@ -56,7 +54,7 @@ impl Default for Chunk { Chunk { blocks: [BlockType::Void; CHUNK_MEM_SIZE], block_data: [BlockData::None; CHUNK_MEM_SIZE], - position: ChunkPos { x: 0, y: 0 }, + position: ChunkPos::new(0, 0), dirty_blocks: Vec::new(), } } @@ -72,6 +70,10 @@ impl Chunk { } } + pub fn get_id(&self) -> ChunkId { + self.position.to_id() + } + pub fn get_all_blocks(&self) -> Vec { self.blocks .iter() @@ -83,6 +85,15 @@ impl Chunk { .collect() } + pub fn get_all_world_blocks(&self) -> Vec { + self.blocks + .iter() + .enumerate() + .filter(|(_i, &b)| b != BlockType::Void) + .map(|(index, _block_type)| self.get_world_block_from_index(index)) + .collect() + } + /** * Returns dirty blocks plus all the visible blocks */ @@ -94,8 +105,16 @@ impl Chunk { .collect() } - pub fn get_uuid(&self) -> String { - self.position.to_index() + pub fn get_all_world_blocks_and_dirty(&self) -> Vec { + self.dirty_blocks + .iter() + .map(|pos| self.get_world_block(pos)) + .chain(self.get_all_world_blocks().into_iter()) + .collect() + } + + pub fn get_uuid(&self) -> u64 { + self.position.to_id() } pub fn add_block(&mut self, block: ChunkBlock) { @@ -131,7 +150,7 @@ impl Chunk { } } - fn get_block_type(&self, pos: &InnerChunkPos) -> BlockType { + pub fn get_block_type(&self, pos: &InnerChunkPos) -> BlockType { self.get_block_type_at_index(pos.to_chunk_index()) } diff --git a/lib/world/src/chunk/chunk_duct.rs b/lib/world/src/chunk/chunk_duct.rs index 256b221..ac511c4 100644 --- a/lib/world/src/chunk/chunk_duct.rs +++ b/lib/world/src/chunk/chunk_duct.rs @@ -1,6 +1,5 @@ use crate::{ - chunk::{Chunk, InnerChunkPos}, - positions::ChunkPos, + chunk::{chunk::Chunk, chunk_pos::ChunkPos, inner_chunk_pos::InnerChunkPos}, world::world_block::WorldBlock, }; use serde_wasm_bindgen::{from_value, to_value, Error}; @@ -15,8 +14,8 @@ impl Chunk { }) } - pub fn get_chunk_id(&self) -> String { - self.position.to_index() + pub fn get_chunk_id(&self) -> u64 { + self.position.to_id() } pub fn add_block_wasm(&mut self, js_block: JsValue) -> Result<(), Error> { diff --git a/lib/world/src/chunk/chunk_fetcher.rs b/lib/world/src/chunk/chunk_fetcher.rs new file mode 100644 index 0000000..94bcf5b --- /dev/null +++ b/lib/world/src/chunk/chunk_fetcher.rs @@ -0,0 +1,234 @@ +use crate::chunk::chunk_pos::ChunkPos; +use crate::game::Game; +use crate::terrain_gen::TerrainGenerator; +use crate::{chunk::chunk::Chunk, utils::js_log}; +use js_sys; +use serde::{Deserialize, Serialize}; +use std::cell::RefCell; +use std::rc::Rc; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::JsFuture; +use web_sys::{Request, RequestInit, RequestMode, Response}; + +/// Shared state for tracking an in-flight async chunk load +type InFlightResult = Rc>>>; + +/// An in-flight chunk request with its position and result state +#[derive(Clone)] +struct InFlightChunk { + pos: ChunkPos, + result: InFlightResult, +} + +#[derive(Clone, Serialize, Deserialize)] +#[wasm_bindgen(getter_with_clone)] +pub struct ChunkFetcher { + chunks_to_load: Vec, + chunk_loader: ChunkLoader, + /// Tracks all currently loading chunks (not serialized) + #[serde(skip)] + in_flight: Vec, +} + +#[derive(Clone, Serialize, Deserialize)] +pub enum ChunkLoader { + TerrainGenerator(TerrainGenerator), + Server(ServerChunkLoader), +} + +impl ChunkFetcher { + pub fn new(chunk_loader: ChunkLoader) -> Self { + Self { + chunks_to_load: Vec::new(), + chunk_loader, + in_flight: Vec::new(), + } + } + + pub fn request_chunk(&mut self, chunk_pos: ChunkPos) { + // Check if already queued + if self.chunks_to_load.iter().any(|pos| pos == &chunk_pos) { + return; + } + // Check if already in-flight + if self + .in_flight + .iter() + .any(|inflight| inflight.pos == chunk_pos) + { + return; + } + js_log(&format!( + "chunk_fetcher.rs: Requesting chunk: {:?}", + chunk_pos + )); + self.chunks_to_load.push(chunk_pos); + } + + /// Attempts to get a loaded chunk. Returns `Some(chunk)` if one is ready, + /// or `None` if still loading or no chunks are pending. + /// + /// For server-loaded chunks, this spawns async fetches in the background + /// and returns chunks as they complete on subsequent calls. + pub fn consume_single_chunk(&mut self) -> Option { + // 1. Check if any in-flight request has completed + let mut completed_index = None; + for (i, in_flight) in self.in_flight.iter().enumerate() { + if in_flight.result.borrow().is_some() { + completed_index = Some(i); + break; + } + } + + if let Some(index) = completed_index { + let in_flight = self.in_flight.remove(index); + let result = in_flight.result.borrow_mut().take().unwrap(); + match result { + Ok(chunk) => return Some(chunk), + Err(e) => { + js_log(&format!("Chunk load failed: {}", e)); + // Continue to try starting new requests or check other in-flight + } + } + } + + // 2. Start new requests for any pending chunks + while let Some(chunk_pos) = self.chunks_to_load.pop() { + match &self.chunk_loader { + ChunkLoader::TerrainGenerator(loader) => { + // Sync case - return immediately + return Some(loader.get_chunk(chunk_pos.x, chunk_pos.y)); + } + ChunkLoader::Server(loader) => { + // Async case - spawn background task + let result: InFlightResult = Rc::new(RefCell::new(None)); + let result_clone = result.clone(); + let loader_clone = loader.clone(); + + wasm_bindgen_futures::spawn_local(async move { + let fetch_result = loader_clone.load_chunk(chunk_pos).await; + let mapped = fetch_result.map_err(|e| format!("{:?}", e)); + *result_clone.borrow_mut() = Some(mapped); + }); + + self.in_flight.push(InFlightChunk { + pos: chunk_pos, + result, + }); + } + } + } + + None // No chunks ready yet + } + + pub fn get_chunk_to_load_count(&self) -> usize { + self.chunks_to_load.len() + } +} + +#[wasm_bindgen] +impl ChunkFetcher { + #[wasm_bindgen(js_name = "makeFromTerrainGenerator")] + pub fn make_from_terrain_generator(loader: TerrainGenerator) -> Self { + Self::new(ChunkLoader::TerrainGenerator(loader)) + } + + #[wasm_bindgen(js_name = "makeFromServerChunkLoader")] + pub fn make_from_server_chunk_loader(loader: ServerChunkLoader) -> Self { + Self::new(ChunkLoader::Server(loader)) + } + + #[wasm_bindgen(js_name = "deserialize")] + pub fn deserialize(js_value: JsValue) -> Result { + serde_wasm_bindgen::from_value(js_value) + .map_err(|e| JsValue::from_str(&format!("Failed to deserialize ChunkFetcher: {}", e))) + } +} + +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "setChunkFetcherConfig")] + pub fn set_chunk_fetcher_config(&mut self, config: JsValue) { + self.chunk_fetcher.chunk_loader = serde_wasm_bindgen::from_value(config).unwrap(); + } + + #[wasm_bindgen(js_name = "serializeChunkFetcher")] + pub fn serialize(&self) -> Result { + serde_wasm_bindgen::to_value(&self.chunk_fetcher) + .map_err(|_| JsValue::from_str("Failed to serialize ChunkFetcher")) + } + + #[wasm_bindgen(js_name = "getPendingChunkCount")] + pub fn get_pending_chunk_count(&self) -> usize { + self.chunk_fetcher.chunks_to_load.len() + self.chunk_fetcher.in_flight.len() + } +} + +#[derive(Clone, Serialize, Deserialize)] +#[wasm_bindgen] +pub struct ServerChunkLoader { + base_url: String, + game_id: String, +} + +#[wasm_bindgen] +impl ServerChunkLoader { + #[wasm_bindgen(constructor)] + pub fn new(base_url: String, game_id: String) -> Self { + Self { base_url, game_id } + } +} + +impl ServerChunkLoader { + pub async fn load_chunk(&self, chunk_pos: ChunkPos) -> Result { + let url = format!( + "{}/game/{}/chunk/{}/{}", + self.base_url, self.game_id, chunk_pos.x, chunk_pos.y + ); + + loop { + let opts = RequestInit::new(); + opts.set_method("GET"); + opts.set_mode(RequestMode::Cors); + + let request = Request::new_with_str_and_init(&url, &opts)?; + + request + .headers() + .set("Accept", "application/vnd.github.v3+json")?; + + let window = web_sys::window().unwrap(); + let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?; + + // `resp_value` is a `Response` object. + assert!(resp_value.is_instance_of::()); + let resp: Response = resp_value.dyn_into().unwrap(); + + // Handle not found - wait and retry + if resp.status() == 404 { + js_log(&format!( + "Chunk requested at ({}, {}), retrying in 1 second...", + chunk_pos.x, chunk_pos.y + )); + // Sleep for 1 second before retrying + let promise = js_sys::Promise::new(&mut |resolve, _| { + let window = web_sys::window().unwrap(); + window + .set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, 1000) + .unwrap(); + }); + JsFuture::from(promise).await?; + continue; + } + + // Convert this other `Promise` into a rust `Future`. + let json = JsFuture::from(resp.json()?).await?; + + let chunk = Chunk::deserialize(json)?; + + // Send the JSON response back to JS. + return Ok(chunk); + } + } +} diff --git a/lib/world/src/chunk/chunk_mesh.rs b/lib/world/src/chunk/chunk_mesh.rs index 8d180a1..721d6d3 100644 --- a/lib/world/src/chunk/chunk_mesh.rs +++ b/lib/world/src/chunk/chunk_mesh.rs @@ -1,15 +1,19 @@ use crate::{ - direction::Directions, - plane::WorldPlane, - positions::{ChunkPos, InnerChunkPos, WorldPos}, + chunk::{chunk_pos::ChunkPos, inner_chunk_pos::InnerChunkPos}, + components::world_pos::WorldPos, + geometry::direction::Directions, + geometry::plane::WorldPlane, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use wasm_bindgen::prelude::wasm_bindgen; #[derive(Serialize, Deserialize, Clone)] +#[wasm_bindgen] pub struct ChunkMesh { - face_map: HashMap, - chunk_pos: ChunkPos, + #[wasm_bindgen(skip)] + pub face_map: HashMap, + pub chunk_pos: ChunkPos, } #[derive(PartialEq, Debug, Serialize, Deserialize)] @@ -80,8 +84,10 @@ impl IntoIterator for &ChunkMesh { mod tests { use crate::{ chunk::chunk_mesh::{BlockMesh, ChunkMesh}, - direction::Directions, - positions::{ChunkPos, WorldPos}, + chunk::chunk_pos::ChunkPos, + components::world_pos::WorldPos, + geometry::direction::Directions, + geometry::vec::Vector3Ops, }; #[test] @@ -90,9 +96,9 @@ mod tests { let mut chunk_mesh = ChunkMesh::new(chunk_pos); let world_pos = WorldPos::new(0, 0, 0); let directions = Directions::all(); - chunk_mesh.insert(world_pos, directions); + chunk_mesh.insert(world_pos.clone(), directions); assert_eq!( - chunk_mesh.get(world_pos), + chunk_mesh.get(world_pos.clone()), BlockMesh { world_pos, directions @@ -106,7 +112,7 @@ mod tests { let chunk_mesh = ChunkMesh::new(chunk_pos); let world_pos = WorldPos::new(0, 0, 0); assert_eq!( - chunk_mesh.get(world_pos), + chunk_mesh.get(world_pos.clone()), BlockMesh { world_pos, directions: Directions::empty() diff --git a/lib/world/src/chunk/chunk_pos.rs b/lib/world/src/chunk/chunk_pos.rs new file mode 100644 index 0000000..06bde7a --- /dev/null +++ b/lib/world/src/chunk/chunk_pos.rs @@ -0,0 +1,121 @@ +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::wasm_bindgen; + +use crate::{ + chunk::chunk::CHUNK_WIDTH, components::world_pos::WorldPos, + entities::entity_component::impl_component, geometry::vec2::impl_vec2_ops, +}; + +use super::chunk::ChunkId; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[wasm_bindgen] +pub struct ChunkPos { + pub x: i16, + pub y: i16, +} + +impl_component!(ChunkPos); +impl_vec2_ops!(ChunkPos, i16); + +#[wasm_bindgen] +impl ChunkPos { + pub fn to_world_index(&self) -> i32 { + let x = self.x as i32; + let y = self.y as i32; + x + (y << 16) + } + + pub fn to_id(&self) -> u64 { + let a = if self.x >= 0 { + (2 * self.x as i64) as u64 + } else { + (-2 * self.x as i64 - 1) as u64 + }; + + let b = if self.y >= 0 { + (2 * self.y as i64) as u64 + } else { + (2 * -self.y as i64 - 1) as u64 + }; + + ((a + b) * (a + b + 1)) / 2 + a + } + + pub fn from_id(z: ChunkId) -> ChunkPos { + let w = (((8 * z + 1) as f64).sqrt() - 1.0) / 2.0; + let w = w.floor() as u64; + let t = (w * w + w) / 2; + let a = (z - t) as i32; + let b = (w as i32) - a; + + let x = if a % 2 == 0 { + (a / 2) as i16 + } else { + (-(a + 1) / 2) as i16 + }; + + let y = if b % 2 == 0 { + (b / 2) as i16 + } else { + (-(b + 1) / 2) as i16 + }; + + ChunkPos { x, y } + } + + pub fn to_world_pos(&self) -> WorldPos { + WorldPos { + x: self.x as i32 * CHUNK_WIDTH as i32 + CHUNK_WIDTH as i32 / 2, + y: 0, + z: self.y as i32 * CHUNK_WIDTH as i32 + CHUNK_WIDTH as i32 / 2, + } + } + + #[wasm_bindgen(constructor)] + pub fn new(x: i16, y: i16) -> Self { + ChunkPos { x, y } + } + + pub fn add(&self, vec: &ChunkPos) -> Self { + ChunkPos { + x: self.x + vec.x, + y: self.y + vec.y, + } + } + + pub fn scalar_mul(&self, val: i16) -> Self { + ChunkPos { + x: self.x * val, + y: self.y * val, + } + } + + pub fn move_to_3d(&self, y_val: i16) -> WorldPos { + WorldPos { + x: self.x as i32, + y: y_val as i32, + z: self.y as i32, + } + } + + pub fn get_adjacent_vecs(&self) -> Vec { + let mut vecs = Vec::new(); + vecs.push(self.clone()); + vecs.push(self.add(&ChunkPos::new(0, 1))); + vecs.push(self.add(&ChunkPos::new(1, 0))); + vecs.push(self.add(&ChunkPos::new(-1, 0))); + vecs.push(self.add(&ChunkPos::new(0, -1))); + vecs + } +} + +impl std::ops::Add for ChunkPos { + type Output = ChunkPos; + fn add(self, other: ChunkPos) -> ChunkPos { + ChunkPos { + x: self.x + other.x, + y: self.y + other.y, + } + } +} diff --git a/lib/world/src/chunk/chunk_unit_tests.rs b/lib/world/src/chunk/chunk_unit_tests.rs index 575111a..cb2250c 100644 --- a/lib/world/src/chunk/chunk_unit_tests.rs +++ b/lib/world/src/chunk/chunk_unit_tests.rs @@ -1,7 +1,8 @@ -use super::{Chunk, ChunkPos, InnerChunkPos}; use crate::{ - block::{BlockData, BlockType}, - chunk::ChunkBlock, + block::{BlockData, BlockType, ChunkBlock}, + chunk::{chunk::Chunk, chunk_pos::ChunkPos, inner_chunk_pos::InnerChunkPos}, + components::world_pos::WorldPos, + geometry::vec::Vector3Ops, world::World, }; @@ -130,3 +131,129 @@ fn deletes_blocks() { assert_eq!(block, BlockType::Void) } + +#[test] +fn index_conversion() { + fn do_test(index: usize, inner_chunk_pos: InnerChunkPos) -> () { + assert_eq!(inner_chunk_pos.to_chunk_index(), index); + assert_eq!(InnerChunkPos::make_from_chunk_index(index), inner_chunk_pos); + } + + do_test(1024 + 32 + 3, InnerChunkPos::new(1, 2, 3)); + do_test(0, InnerChunkPos::new(0, 0, 0)); +} + +#[test] +fn inner_chunk_pos_to_chunk_index() { + fn do_test(inner_chunk_pos: InnerChunkPos) { + let index = inner_chunk_pos.to_chunk_index(); + let inner_chunk_pos2 = InnerChunkPos::make_from_chunk_index(index); + assert_eq!(inner_chunk_pos, inner_chunk_pos2); + } + + do_test(InnerChunkPos::new(0, 0, 0)); + do_test(InnerChunkPos::new(15, 15, 15)); +} + +#[test] +fn inner_chunk_pos_to_world_pos() { + fn do_test(inner_chunk_pos: InnerChunkPos, chunk_pos: ChunkPos, world_pos: WorldPos) { + assert_eq!(inner_chunk_pos.to_world_pos(&chunk_pos), world_pos); + } + + do_test( + InnerChunkPos::new(1, 2, 3), + ChunkPos { x: 0, y: 0 }, + WorldPos { x: 1, y: 2, z: 3 }, + ); + + do_test( + InnerChunkPos::new(1, 2, 3), + ChunkPos { x: 1, y: 1 }, + WorldPos { x: 17, y: 2, z: 19 }, + ); + + do_test( + InnerChunkPos::new(1, 2, 3), + ChunkPos { x: -1, y: -1 }, + WorldPos { + x: -15, + y: 2, + z: -13, + }, + ); + + do_test( + InnerChunkPos::new(15, 0, 15), + ChunkPos { x: -2, y: -3 }, + WorldPos { + x: -17, + y: 0, + z: -33, + }, + ); +} + +#[test] +fn world_pos_to_chunk_pos() { + assert_eq!( + WorldPos { x: 1, y: 2, z: 3 }.to_chunk_pos(), + ChunkPos { x: 0, y: 0 } + ); + assert_eq!( + WorldPos { x: 0, y: 0, z: 0 }.to_chunk_pos(), + ChunkPos { x: 0, y: 0 } + ); + assert_eq!( + WorldPos { x: -1, y: 0, z: -1 }.to_chunk_pos(), + ChunkPos { x: -1, y: -1 } + ); + + assert_eq!( + WorldPos { + x: -16, + y: 0, + z: -16, + } + .to_chunk_pos(), + ChunkPos { x: -1, y: -1 } + ); + + assert_eq!( + WorldPos { x: 16, y: 0, z: 0 }.to_chunk_pos(), + ChunkPos { x: 1, y: 0 } + ); + + assert_eq!( + WorldPos { x: 0, y: 0, z: -1 }.to_chunk_pos(), + ChunkPos { x: 0, y: -1 } + ); +} + +#[test] +fn world_pos_to_inner_chunk_pos() { + assert_eq!( + WorldPos { x: 1, y: 2, z: 3 }.to_inner_chunk_pos(), + InnerChunkPos::new(1, 2, 3) + ); + + assert_eq!( + WorldPos { x: -1, y: 0, z: 1 }.to_inner_chunk_pos(), + InnerChunkPos::new(15, 0, 1) + ); + + assert_eq!( + WorldPos { x: -1, y: 0, z: -1 }.to_inner_chunk_pos(), + InnerChunkPos::new(15, 0, 15) + ); + + assert_eq!( + WorldPos { + x: -32, + y: 20, + z: 0, + } + .to_inner_chunk_pos(), + InnerChunkPos::new(0, 20, 0) + ); +} diff --git a/lib/world/src/chunk/inner_chunk_pos.rs b/lib/world/src/chunk/inner_chunk_pos.rs new file mode 100644 index 0000000..16cd498 --- /dev/null +++ b/lib/world/src/chunk/inner_chunk_pos.rs @@ -0,0 +1,42 @@ +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::wasm_bindgen; + +use crate::{ + chunk::{chunk_pos::ChunkPos, CHUNK_WIDTH}, + components::world_pos::WorldPos, + entities::entity_component::impl_component, + geometry::vec::{impl_vector_ops, Vector3Ops}, +}; + +#[wasm_bindgen] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct InnerChunkPos { + x: i8, + y: i8, + z: i8, +} + +impl_component!(InnerChunkPos); +impl_vector_ops!(InnerChunkPos, i8); + +#[wasm_bindgen] +impl InnerChunkPos { + pub fn to_chunk_index(&self) -> usize { + let x_part = (self.x as usize) << (4 + 6); + let y_part = (self.y as usize) << 4; + let z_part = self.z as usize; + x_part + y_part + z_part + } + + pub fn make_from_chunk_index(index: usize) -> InnerChunkPos { + let x_part = (index >> (4 + 6)) as i8; + let y_part = ((index & 0b1111110000) >> 4) as i8; + let z_part = (index & 0b1111) as i8; + InnerChunkPos::new(x_part, y_part, z_part) + } + + pub fn to_world_pos(&self, chunk_pos: &ChunkPos) -> WorldPos { + let pos = chunk_pos.scalar_mul(CHUNK_WIDTH).move_to_3d(0).add(self); + WorldPos::new(pos.x() as i32, pos.y() as i32, pos.z() as i32) + } +} diff --git a/lib/world/src/chunk/mod.rs b/lib/world/src/chunk/mod.rs new file mode 100644 index 0000000..bdd2657 --- /dev/null +++ b/lib/world/src/chunk/mod.rs @@ -0,0 +1,9 @@ +pub mod chunk; +pub mod chunk_duct; +pub mod chunk_fetcher; +pub mod chunk_mesh; +pub mod chunk_pos; +#[cfg(test)] +pub mod chunk_unit_tests; +pub mod inner_chunk_pos; +pub use chunk::{Chunk, CHUNK_HEIGHT, CHUNK_WIDTH}; diff --git a/lib/world/src/components/fine_world_pos.rs b/lib/world/src/components/fine_world_pos.rs new file mode 100644 index 0000000..d360ff2 --- /dev/null +++ b/lib/world/src/components/fine_world_pos.rs @@ -0,0 +1,91 @@ +use crate::components::world_pos::WorldPos; +use crate::{entities::entity_component::impl_component, geometry::vec::impl_vector_ops}; +use serde::{Deserialize, Serialize}; +use std::ops::Add; +use wasm_bindgen::prelude::*; + +use super::velocity::Velocity; + +const PRECISION: f32 = 0.001; // Precision to three decimal places + +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq)] +#[wasm_bindgen] +pub struct FineWorldPos { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl_component!(FineWorldPos); + +impl_vector_ops!(FineWorldPos, f32); + +impl FineWorldPos { + pub fn new(x: f32, y: f32, z: f32) -> Self { + Self { x, y, z } + } + + pub fn to_world_pos(&self) -> WorldPos { + WorldPos { + x: self.x as i32, + y: self.y as i32, + z: self.z as i32, + } + } + + pub fn round(&mut self) { + self.x = (self.x / PRECISION).round() * PRECISION; + self.y = (self.y / PRECISION).round() * PRECISION; + self.z = (self.z / PRECISION).round() * PRECISION; + } + + pub fn equal(&self, other: &FineWorldPos) -> bool { + (self.x - other.x).abs() < PRECISION + && (self.y - other.y).abs() < PRECISION + && (self.z - other.z).abs() < PRECISION + } +} + +impl Add for FineWorldPos { + type Output = Self; + + fn add(self, other: Velocity) -> Self { + Self { + x: self.x + other.x, + y: self.y + other.y, + z: self.z + other.z, + } + } +} + +#[cfg(test)] +pub mod tests { + use crate::{components::fine_world_pos::FineWorldPos, geometry::vec::Vector3Ops}; + + #[test] + fn test_distance_to() { + let vec1 = FineWorldPos { + x: 0 as f32, + y: 0 as f32, + z: 0 as f32, + }; + let vec2 = FineWorldPos { + x: 1 as f32, + y: 1 as f32, + z: 1 as f32, + }; + assert_eq!(vec1.distance_to(&vec2), 1.7320508); + + let vec1 = FineWorldPos { + x: 0 as f32, + y: 0 as f32, + z: 0 as f32, + }; + let vec2 = FineWorldPos { + x: 1 as f32, + y: 0 as f32, + z: 0 as f32, + }; + assert_eq!(vec1.distance_to(&vec2), 1.0); + } +} diff --git a/lib/world/src/components/mod.rs b/lib/world/src/components/mod.rs new file mode 100644 index 0000000..88cfae3 --- /dev/null +++ b/lib/world/src/components/mod.rs @@ -0,0 +1,4 @@ +pub mod fine_world_pos; +pub mod velocity; +pub mod world_pos; +pub mod size3; \ No newline at end of file diff --git a/lib/world/src/components/size3.rs b/lib/world/src/components/size3.rs new file mode 100644 index 0000000..43f3aa9 --- /dev/null +++ b/lib/world/src/components/size3.rs @@ -0,0 +1,21 @@ +use crate::{entities::entity_component::impl_component, geometry::vec::impl_vector_ops}; +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::*; + +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq)] +#[wasm_bindgen] +pub struct Size3 { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl Size3 { + pub fn new(x: f32, y: f32, z: f32) -> Self { + Self { x, y, z } + } +} + +impl_component!(Size3); + +impl_vector_ops!(Size3, f32); diff --git a/lib/world/src/components/velocity.rs b/lib/world/src/components/velocity.rs new file mode 100644 index 0000000..14be886 --- /dev/null +++ b/lib/world/src/components/velocity.rs @@ -0,0 +1,28 @@ +use crate::{entities::entity_component::impl_component, geometry::vec::impl_vector_ops}; +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::*; + +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)] +#[wasm_bindgen] +pub struct Velocity { + pub x: f32, + pub y: f32, + pub z: f32, +} + +impl_component!(Velocity); +impl_vector_ops!(Velocity, f32); + +impl Velocity { + pub fn new(x: f32, y: f32, z: f32) -> Velocity { + Velocity { x, y, z } + } + + pub fn zero() -> Velocity { + Velocity { + x: 0.0, + y: 0.0, + z: 0.0, + } + } +} diff --git a/lib/world/src/components/world_pos.rs b/lib/world/src/components/world_pos.rs new file mode 100644 index 0000000..992f419 --- /dev/null +++ b/lib/world/src/components/world_pos.rs @@ -0,0 +1,70 @@ +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::*; + +use crate::{ + chunk::{chunk_pos::ChunkPos, inner_chunk_pos::InnerChunkPos, CHUNK_HEIGHT, CHUNK_WIDTH}, + entities::entity_component::impl_component, + geometry::vec::{impl_vector_ops, Vector3Ops}, +}; + +use super::fine_world_pos::FineWorldPos; + +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +#[wasm_bindgen] +pub struct WorldPos { + pub x: i32, + pub y: i32, + pub z: i32, +} + +impl_component!(WorldPos); + +impl_vector_ops!(WorldPos, i32); + +#[wasm_bindgen] +impl WorldPos { + #[wasm_bindgen(constructor)] + pub fn new_wasm(x: i32, y: i32, z: i32) -> WorldPos { + WorldPos { x, y, z } + } + + pub fn is_valid(&self) -> bool { + self.y >= 0 && self.y < 256 + } + + pub fn to_fine_world_pos(&self) -> FineWorldPos { + FineWorldPos { + x: self.x as f32, + y: self.y as f32, + z: self.z as f32, + } + } + + pub fn to_inner_chunk_pos(&self) -> InnerChunkPos { + let x = + (((self.x as i8 % CHUNK_WIDTH as i8) + CHUNK_WIDTH as i8) % CHUNK_WIDTH as i8) as i8; + let y = ((self.y as i8 % CHUNK_HEIGHT as i8) + CHUNK_HEIGHT as i8) % CHUNK_HEIGHT as i8; + let z = + (((self.z as i8 % CHUNK_WIDTH as i8) + CHUNK_WIDTH as i8) % CHUNK_WIDTH as i8) as i8; + InnerChunkPos::new(x, y, z) + } + + pub fn to_chunk_pos(&self) -> ChunkPos { + let x = if self.x < 0 { + ((self.x + 1) / CHUNK_WIDTH as i32) - 1 + } else { + self.x / CHUNK_WIDTH as i32 + }; + + let y = if self.z < 0 { + ((self.z + 1) / CHUNK_WIDTH as i32) - 1 + } else { + self.z / CHUNK_WIDTH as i32 + }; + + ChunkPos { + x: x as i16, + y: y as i16, + } + } +} diff --git a/lib/world/src/entities/entities.rs b/lib/world/src/entities/entities.rs new file mode 100644 index 0000000..1a2ce6c --- /dev/null +++ b/lib/world/src/entities/entities.rs @@ -0,0 +1,172 @@ +use crate::game::Game; + +use super::entity::{Entity, EntityId}; +use super::entity_component::Component; +use super::fireball::Fireball; +use super::player::Player; +use serde::{Deserialize, Serialize}; +use serde_wasm_bindgen::{from_value, to_value}; +use std::collections::HashSet; +use std::{any::TypeId, fmt::Debug}; +use wasm_bindgen::prelude::*; + +#[derive(Debug)] +pub struct EntityQuery { + type_ids: Vec, +} + +impl EntityQuery { + pub fn new() -> Self { + Self { type_ids: vec![] } + } + + pub fn add(&mut self) { + self.type_ids.push(TypeId::of::()); + } +} + +// New struct to hold mutable references to filtered entities +#[derive(Debug)] +pub struct EntityQueryResults<'a> { + pub entities: Vec<&'a mut Entity>, +} + +impl<'a> EntityQueryResults<'a> { + pub fn new(entities: Vec<&'a mut Entity>) -> Self { + Self { entities } + } + + pub fn len(&self) -> usize { + self.entities.len() + } +} + +#[wasm_bindgen] +#[derive(Debug, Serialize, Deserialize)] +pub struct Entities { + entities: Vec, +} + +impl Clone for Entities { + fn clone(&self) -> Self { + Entities { + entities: self.entities.clone(), + } + } +} + +impl Entities { + pub fn new() -> Entities { + Entities { + entities: Vec::new(), + } + } + + pub fn get_entity_by_id(&self, id: EntityId) -> Option<&Entity> { + self.entities.iter().find(|entity| entity.id == id) + } + + pub fn get_entity_by_id_mut(&mut self, id: EntityId) -> Option<&mut Entity> { + self.entities.iter_mut().find(|entity| entity.id == id) + } + + pub fn get_all(&self) -> &Vec { + &self.entities + } + + pub fn get_all_entity_ids(&self) -> HashSet { + self.entities.iter().map(|entity| entity.id).collect() + } + + pub fn get_all_mut(&mut self) -> &mut Vec { + &mut self.entities + } + + pub fn query(&mut self, filter: &EntityQuery) -> EntityQueryResults { + let filtered_entities = self + .entities + .iter_mut() + .filter(|entity| { + filter + .type_ids + .iter() + .all(|&type_id| entity.has_typeid(type_id)) + }) + .collect(); + + EntityQueryResults::new(filtered_entities) + } +} + +impl Entities { + pub fn add_entity(&mut self, entity: Entity) { + self.entities.push(entity); + } + + pub fn get_entity(&self, id: EntityId) -> Option { + self.entities.iter().find(|entity| entity.id == id).cloned() + } + + pub fn to_js(&self) -> JsValue { + to_value(self).unwrap() + } + + pub fn get_entity_as_player(&self, id: EntityId) -> Option { + self.get_entity_by_id(id).map(|entity| entity.as_player()) + } + + pub fn get_entity_as_fireball(&self, id: EntityId) -> Option { + self.get_entity_by_id(id).map(|entity| entity.as_fireball()) + } + + pub fn get_all_clone(&self) -> Vec { + self.entities.clone() + } + + pub fn get_entity_by_id_clone(&self, id: EntityId) -> Option { + self.get_entity_by_id(id).map(|entity| entity.clone()) + } +} + +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "getEntityAsPlayer")] + pub fn get_entity_as_player(&self, id: EntityId) -> Option { + self.entities.get_entity_as_player(id) + } + + #[wasm_bindgen(js_name = "getEntityById")] + pub fn get_entity_by_id(&self, id: EntityId) -> Option { + self.entities.get_entity_by_id_clone(id) + } + + #[wasm_bindgen(js_name = "getAllEntities")] + pub fn get_all_entities(&self) -> Vec { + self.entities.get_all_clone() + } + + #[wasm_bindgen(js_name = "serializeEntities")] + pub fn serialize_entities(&self) -> JsValue { + to_value(&self.entities).unwrap() + } + + #[wasm_bindgen(js_name = "addEntity")] + pub fn add_entity(&mut self, entity: Entity) { + self.entities.add_entity(entity); + } + + #[wasm_bindgen(js_name = "replaceEntities")] + pub fn replace_entities(&mut self, entities_js: JsValue) -> Result<(), serde_wasm_bindgen::Error> { + let entities: Entities = from_value(entities_js)?; + self.entities = entities; + Ok(()) + } +} + +#[wasm_bindgen] +impl Entities { + #[wasm_bindgen(js_name = "deserialize")] + pub fn from_js(value: JsValue) -> Result { + from_value(value) + } +} diff --git a/lib/world/src/entities/entity.rs b/lib/world/src/entities/entity.rs new file mode 100644 index 0000000..41c4cde --- /dev/null +++ b/lib/world/src/entities/entity.rs @@ -0,0 +1,202 @@ +use crate::utils::js_log; + +use super::entity_component::{Component, COMPONENT_REGISTRY}; +use super::fireball::Fireball; +use super::player::Player; +use rand::Rng; +use serde::{de, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer}; +use std::{any::TypeId, fmt::Debug}; +use wasm_bindgen::prelude::*; + +pub type EntityId = u32; + +pub fn make_entity_id() -> EntityId { + rand::thread_rng().gen_range(0..=u32::MAX) +} + +#[derive(Debug)] +#[wasm_bindgen(getter_with_clone)] +pub struct Entity { + pub id: EntityId, + pub name: String, + components: Vec>, +} + +impl Serialize for Entity { + fn serialize(&self, serializer: S) -> Result { + let mut s = serializer.serialize_struct("Entity", 2)?; + s.serialize_field("id", &self.id)?; + s.serialize_field("name", &self.name)?; + + // Convert components into serializable format + let comps: Vec<_> = self + .components + .iter() + .map(|c| { + let type_name = c.type_name(); + let value = c.to_json().to_string(); + + return (type_name, value); + }) + .collect(); + + js_log(&format!("Components: {:?}", comps)); + + s.serialize_field("components", &comps)?; + s.end() + } +} + +impl<'de> Deserialize<'de> for Entity { + fn deserialize>(deserializer: D) -> Result { + #[derive(Deserialize)] + struct EntityHelper { + id: EntityId, + name: String, + components: Vec<(String, String)>, + } + + let EntityHelper { + id, + name, + components, + } = EntityHelper::deserialize(deserializer)?; + let mut entity = Entity::new(id, name); + + let registry = COMPONENT_REGISTRY.lock().unwrap(); + for item in components { + let (type_name, value) = item; + + let parsed_value = serde_json::from_str(&value).map_err(de::Error::custom)?; + + let all_type_names = registry.keys().cloned().collect::>(); + + let deser = registry.get(type_name.as_str()).ok_or_else(|| { + de::Error::custom(format!( + "Unknown component: {} all_type_names: {:?}", + type_name, all_type_names + )) + })?; + + entity.components.push(deser(parsed_value)); + } + + Ok(entity) + } +} + +impl Clone for Entity { + fn clone(&self) -> Self { + Entity { + id: self.id, + name: self.name.clone(), + components: self.components.iter().map(|c| c.clone()).collect(), + } + } +} + +impl Entity { + pub fn new(id: EntityId, name: String) -> Self { + Self { + id, + name, + components: Vec::new(), + } + } + + pub fn add(&mut self, component: T) { + self.components.push(Box::new(component)); + } + + pub fn get(&self) -> Option<&T> { + self.components + .iter() + .find_map(|c| c.as_any().downcast_ref::()) + } + + pub fn set(&mut self, component: T) { + self.components + .retain(|c| c.as_any().type_id() != TypeId::of::()); + self.components.push(Box::new(component)); + } + + pub fn has(&self) -> bool { + self.components + .iter() + .any(|c| c.as_any().type_id() == TypeId::of::()) + } + + pub fn has_typeid(&self, type_id: TypeId) -> bool { + self.components + .iter() + .any(|c| c.as_any().type_id() == type_id) + } + + pub fn to_json(&self) -> serde_json::Value { + serde_json::to_value(self).unwrap() + } + + pub fn from_json(value: serde_json::Value) -> Result { + serde_json::from_value(value) + } + + pub fn print_components(&self) { + println!("Entity ID: {:?}", self.id); + for component in &self.components { + println!("Component: {:?}", component); + println!("Component Type ID: {:?}", component.as_any().type_id()); + } + } +} + +#[wasm_bindgen] +impl Entity { + pub fn as_player(&self) -> Player { + Player::new(self.clone()) + } + + pub fn as_fireball(&self) -> Fireball { + Fireball::from_entity(self.clone()) + } + + pub fn to_js(&self) -> JsValue { + serde_wasm_bindgen::to_value(self).unwrap() + } + + pub fn from_js(value: JsValue) -> Result { + serde_wasm_bindgen::from_value(value) + } +} + +#[cfg(test)] +mod tests { + use crate::{components::world_pos::WorldPos, geometry::rotation::SphericalRotation}; + + use super::*; + + #[test] + fn test_serialize_deserialize() { + let mut entity = Entity::new(1, "test".to_string()); + let world_pos = WorldPos { x: 1, y: 2, z: 3 }; + let spherical_rotation = SphericalRotation::new(0.0, 0.0); + entity.add(world_pos); + entity.add(spherical_rotation); + let serialized = entity.to_json(); + let deserialized = Entity::from_json(serialized).unwrap(); + + assert_eq!(entity.id, deserialized.id); + assert_eq!(entity.components.len(), deserialized.components.len()); + + let deserialized_world_pos = deserialized.get::().unwrap(); + assert_eq!(world_pos.x, deserialized_world_pos.x); + assert_eq!(world_pos.y, deserialized_world_pos.y); + assert_eq!(world_pos.z, deserialized_world_pos.z); + + let deserialized_spherical_rotation = deserialized.get::().unwrap(); + assert_eq!( + spherical_rotation.theta, + deserialized_spherical_rotation.theta + ); + assert_eq!(spherical_rotation.phi, deserialized_spherical_rotation.phi); + } +} diff --git a/lib/world/src/entities/entity_action.rs b/lib/world/src/entities/entity_action.rs new file mode 100644 index 0000000..c4c100e --- /dev/null +++ b/lib/world/src/entities/entity_action.rs @@ -0,0 +1,227 @@ +use super::entities::Entities; +use super::entity::{Entity, EntityId}; +use crate::game::{Game, GameSchedule}; +use crate::scripts::player_belt_script::{ + SecondaryBeltActionData, SelectItemActionData, UsePrimaryItemActionData, +}; +use crate::scripts::player_jump_script::JumpActionData; +use crate::scripts::player_move_script::MoveActionData; +use crate::scripts::player_rot_script::RotateActionData; +use crate::scripts::player_tp_script::TeleportActionData; +use crate::utils::js_log; +use crate::world::World; +use lazy_static::lazy_static; +use std::any::Any; +use std::collections::HashMap; +use std::fmt::Debug; +use std::sync::Mutex; +use wasm_bindgen::prelude::*; + +pub trait ActionData: Any + Debug { + fn clone_box(&self) -> Box; + + fn as_any(&self) -> &dyn Any; +} + +impl ActionData for T +where + T: Any + Clone + Debug, +{ + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +type ActionSerializer = Box JsValue + Send + Sync>; +type ActionDeserializer = Box EntityActionDto + Send + Sync>; + +lazy_static! { + pub static ref ACTION_REGISTRY: Mutex> = { + let mut map = HashMap::new(); + + fn register_action( + map: &mut HashMap<&'static str, (ActionSerializer, ActionDeserializer)>, + action_name: &'static str, + ) { + let serialize = Box::new(|dto: &EntityActionDto| -> JsValue { + let action_data = dto.get_data::().unwrap(); + let serialized_data = serde_wasm_bindgen::to_value(action_data).unwrap(); + + // Create a JS object with entity_id, name, and data + let obj = js_sys::Object::new(); + js_sys::Reflect::set(&obj, &"entity_id".into(), &dto.entity_id.into()).unwrap(); + js_sys::Reflect::set(&obj, &"name".into(), &dto.name.into()).unwrap(); + js_sys::Reflect::set(&obj, &"data".into(), &serialized_data).unwrap(); + obj.into() + }); + + let deserialize = Box::new(move |entity_id: EntityId, value: JsValue| -> EntityActionDto { + js_log(&format!("Deserializing action id: {:?} data: {:?}", entity_id, value)); + let typed_action: T = serde_wasm_bindgen::from_value(value).unwrap(); + EntityActionDto { + entity_id, + name: action_name, + data: Box::new(typed_action), + } + }); + + map.insert(action_name, (serialize, deserialize)); + } + + // Register all actions in one place! + register_action::(&mut map, "Player-Rotate"); + register_action::(&mut map, "Move"); + register_action::(&mut map, "UseItemAction"); + register_action::(&mut map, "SecondaryBeltAction"); + register_action::(&mut map, "SelectItemAction"); + register_action::(&mut map, "Jump-Action"); + register_action::(&mut map, "Teleport"); + + Mutex::new(map) + }; +} + +#[wasm_bindgen(getter_with_clone)] +#[derive(Debug)] +pub struct EntityActionDto { + pub entity_id: super::entity::EntityId, + #[wasm_bindgen(skip)] + pub name: &'static str, + #[wasm_bindgen(skip)] + pub data: Box, +} + +impl EntityActionDto { + pub fn get_data(&self) -> Option<&T> { + self.data.as_any().downcast_ref::() + } +} + +#[wasm_bindgen] +impl EntityActionDto { + pub fn get_name(&self) -> String { + self.name.to_string() + } + + pub fn to_js(&self) -> JsValue { + let registry = ACTION_REGISTRY + .lock() + .expect("Failed to lock action registry"); + let (serializer, _) = registry.get(self.name).unwrap_or_else(|| { + panic!("Action type '{}' not found in registry", self.name); + }); + serializer(self) + } + + pub fn from_js(js_value: JsValue) -> EntityActionDto { + let obj = js_sys::Object::from(js_value); + + // Extract fields from the JS object + let entity_id: EntityId = js_sys::Reflect::get(&obj, &"entity_id".into()) + .unwrap() + .as_f64() + .unwrap() as u32; + + let name: String = js_sys::Reflect::get(&obj, &"name".into()) + .unwrap() + .as_string() + .unwrap(); + + let data = js_sys::Reflect::get(&obj, &"data".into()).unwrap(); + + js_log(&format!("Deserializing action: {:?}", name)); + + let registry = ACTION_REGISTRY + .lock() + .expect("Failed to lock action registry"); + let (_, deserializer) = registry.get(name.as_str()).unwrap_or_else(|| { + panic!("Action type '{}' not found in registry", name); + }); + + deserializer(entity_id, data) + } +} + +pub trait EntityActionHandler { + fn get_action_type(&self) -> &'static str; + fn handle_dto( + &self, + world: &World, + entity: &mut Entity, + data: &EntityActionDto, + ) -> GameSchedule; +} + +pub trait EntityActionDtoMaker: EntityActionHandler { + fn get_action_type_static() -> &'static str; + + fn make_handler() -> Box + where + Self: Sized + Default + 'static, + { + Box::new(Self::default()) + } + + fn make_dto(entity_id: EntityId, data: T) -> EntityActionDto { + EntityActionDto { + entity_id, + name: Self::get_action_type_static(), + data: Box::new(data), + } + } +} + +#[derive(Default)] +pub struct EntityActionHolder { + actions: Vec, + handlers: Vec>, +} + +impl EntityActionHolder { + pub fn add(&mut self, dto: EntityActionDto) { + self.actions.push(dto); + } + + pub fn add_handler(&mut self, handler: Box) { + self.handlers.push(handler); + } + + pub fn handle_actions(&mut self, world: &World, entity_holder: &mut Entities) -> GameSchedule { + let mut schedule = GameSchedule::empty(); + for action in &self.actions { + // js_log(&format!("Handling action: {:?}", action)); + // js_log(&format!("Action handlers: {:?}", self.handlers.len())); + let entity = entity_holder.get_entity_by_id_mut(action.entity_id); + let mut action_handled = false; + if let Some(entity) = entity { + for handler in &self.handlers { + if handler.get_action_type() == action.name { + let new_schedule = handler.handle_dto(world, entity, action); + schedule.combine(new_schedule); + action_handled = true; + } + } + } + if !action_handled { + js_log(&format!("Action not handled: {:?}", action)); + } + } + + // clear actions + self.actions.clear(); + + schedule + } +} + +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "handleAction")] + pub fn handle_action_wasm(&mut self, action: EntityActionDto) { + self.action_holder.add(action); + } +} diff --git a/lib/world/src/entities/entity_component.rs b/lib/world/src/entities/entity_component.rs new file mode 100644 index 0000000..32bd2d2 --- /dev/null +++ b/lib/world/src/entities/entity_component.rs @@ -0,0 +1,96 @@ +use lazy_static::lazy_static; +use serde_json::Value; +use std::{any::Any, collections::HashMap, fmt::Debug, sync::Mutex}; +use wasm_bindgen::JsValue; + +use crate::{ + components::{ + fine_world_pos::FineWorldPos, size3::Size3, velocity::Velocity, world_pos::WorldPos, + }, + entities::player::Health, + geometry::rotation::SphericalRotation, + scripts::{ + player_belt_script::Belt, player_gravity_script::GravityData, player_jump_script::JumpData, + player_move_script::MovingDirection, velocity_script::Forces, + }, +}; + +pub trait Component: Any + Debug { + fn as_any(&self) -> &dyn Any; + fn as_any_mut(&mut self) -> &mut dyn Any; + fn get_name(&self) -> &str; + fn clone_box(&self) -> Box; + fn type_name(&self) -> &'static str; + fn to_js(&self) -> JsValue; + fn to_json(&self) -> serde_json::Value; +} + +macro_rules! impl_component { + ($type:ty) => { + impl $crate::entities::entity_component::Component for $type { + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + fn get_name(&self) -> &str { + stringify!($type) + } + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + fn type_name(&self) -> &'static str { + std::any::type_name::<$type>() + } + fn to_js(&self) -> wasm_bindgen::prelude::JsValue { + serde_wasm_bindgen::to_value(self).expect("Component must be serializable") + } + fn to_json(&self) -> serde_json::Value { + serde_json::to_value(self).expect("Component must be serializable") + } + } + }; +} +pub(crate) use impl_component; + +impl Clone for Box { + fn clone(&self) -> Box { + self.clone_box() + } +} + +type ComponentDeserializer = fn(Value) -> Box; + +lazy_static! { + pub static ref COMPONENT_REGISTRY: Mutex> = { + let mut map = HashMap::new(); + + fn register( + map: &mut HashMap<&'static str, ComponentDeserializer>, + ) { + fn deser( + v: Value, + ) -> Box { + Box::new(serde_json::from_value::(v).unwrap()) + } + + map.insert(std::any::type_name::(), deser::); + } + + // Register all the components! + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + + Mutex::new(map) + }; +} diff --git a/lib/world/src/entities/fireball.rs b/lib/world/src/entities/fireball.rs new file mode 100644 index 0000000..e3b0b3a --- /dev/null +++ b/lib/world/src/entities/fireball.rs @@ -0,0 +1,178 @@ +use super::{ + entities::{EntityQuery, EntityQueryResults}, + entity::{make_entity_id, Entity}, + player::Health, +}; +use crate::game::GameSchedule; +use crate::scripts::game_script::GameScript; +use crate::scripts::velocity_script::Forces; +use crate::{ + chunk::chunk_fetcher::ChunkFetcher, + components::{fine_world_pos::FineWorldPos, size3::Size3, velocity::Velocity}, + geometry::rect3::Rect3, + utils::js_log, +}; +use serde_json; +use serde_wasm_bindgen; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; + +pub fn make_fireball(pos: FineWorldPos, vel: Velocity) -> Entity { + let uid = make_entity_id(); + let mut ent = Entity::new(uid, "fireball".to_string()); + ent.add::(pos); + ent.add::(vel); + ent.add::(Size3 { + x: 1.0, + y: 1.0, + z: 1.0, + }); + ent.add::(Forces { forces: vec![] }); + ent +} + +#[wasm_bindgen] +pub struct Fireball { + pub pos: FineWorldPos, + pub vel: Velocity, + pub dim: Size3, +} + +#[wasm_bindgen] +impl Fireball { + pub fn from_entity(entity: Entity) -> Fireball { + Fireball { + pos: entity.get::().unwrap().clone(), + vel: entity.get::().unwrap().clone(), + dim: entity.get::().unwrap().clone(), + } + } + + pub fn is_fireball(entity: &Entity) -> bool { + entity.name == "fireball" + } +} + +// Make a gamescript that checks for collisions between fireballs and other entities. + +#[derive(Debug, Default)] +pub struct FireballScript {} + +impl FireballScript { + pub fn name() -> String { + "fireball".to_string() + } +} + +impl GameScript for FireballScript { + fn get_name(&self) -> String { + "fireball".to_string() + } + + fn get_config(&self) -> JsValue { + let config = serde_json::json!({}); + serde_wasm_bindgen::to_value(&config).unwrap() + } + + fn set_config(&mut self, config: JsValue) { + // For now, just log the config. In the future, this could update script behavior + web_sys::console::log_1(&format!("FireballScript config updated: {:?}", config).into()); + } + + fn get_query(&self) -> EntityQuery { + let mut query = EntityQuery::new(); + query.add::(); + query.add::(); + query + } + + fn update( + &mut self, + world: &crate::world::World, + mut query_results: EntityQueryResults, + _chunk_fetcher: &mut ChunkFetcher, + _delta_ms: f32, + ) -> Option { + let mut game_schedule = GameSchedule::empty(); + + // First, collect all the fireball data and other entity data to avoid borrow conflicts + let mut fireball_data = Vec::new(); + let mut other_entity_data = Vec::new(); + + for entity in &query_results.entities { + if Fireball::is_fireball(entity) { + if let (Some(vel), Some(pos), Some(dim)) = ( + entity.get::(), + entity.get::(), + entity.get::(), + ) { + fireball_data.push((entity.id, vel.clone(), pos.clone(), dim.clone())); + } + } else { + if let (Some(pos), Some(dim)) = + (entity.get::(), entity.get::()) + { + other_entity_data.push((entity.id, pos.clone(), dim.clone())); + } + } + } + + // Process fireball collisions with blocks + for (fireball_id, vel, pos, dim) in &fireball_data { + let fireball_rect = Rect3 { + pos: *pos, + dim: *dim, + }; + let fireball_end_pos = *pos + *vel; + + let intersection_info = + world.get_moving_rect3_intersection_info(&fireball_rect, fireball_end_pos); + + if let Some(intersection_info) = intersection_info { + let intersecting_block_pos = intersection_info.world_plane.world_pos; + game_schedule.remove_block(intersecting_block_pos); + game_schedule.remove_entity(*fireball_id); + } + } + + // Process fireball collisions with other entities + for (fireball_id, _vel, fireball_pos, fireball_dim) in &fireball_data { + let fireball_rect = Rect3 { + pos: *fireball_pos, + dim: *fireball_dim, + }; + + for (other_entity_id, other_pos, other_dim) in &other_entity_data { + if fireball_id == other_entity_id { + continue; + } + + let entity2_rect = Rect3 { + pos: *other_pos, + dim: *other_dim, + }; + + if entity2_rect.does_intersect(&fireball_rect) { + js_log(format!("fireball hit entity: {:?}", other_entity_id).as_str()); + game_schedule.remove_entity(*fireball_id); + + // Find the entity to update its health + for entity in &mut query_results.entities { + if entity.id == *other_entity_id { + if let Some(health) = entity.get::() { + let new_health = health.health - 10; + entity.set::(Health { + health: new_health, + max_health: health.max_health, + }); + } + break; + } + } + } + } + } + + Some(game_schedule) + } +} diff --git a/lib/world/src/entities/mod.rs b/lib/world/src/entities/mod.rs new file mode 100644 index 0000000..c6337b9 --- /dev/null +++ b/lib/world/src/entities/mod.rs @@ -0,0 +1,6 @@ +pub mod entities; +pub mod entity; +pub mod entity_action; +pub mod entity_component; +pub mod fireball; +pub mod player; diff --git a/lib/world/src/entities/player.rs b/lib/world/src/entities/player.rs new file mode 100644 index 0000000..b6eca57 --- /dev/null +++ b/lib/world/src/entities/player.rs @@ -0,0 +1,111 @@ +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::wasm_bindgen; + +use super::{ + entity::{Entity, EntityId}, + entity_component::impl_component, +}; +use crate::scripts::player_gravity_script::GravityData; +use crate::scripts::player_jump_script::JumpData; +use crate::scripts::player_move_script::MovingDirection; +use crate::scripts::velocity_script::Forces; +use crate::{ + components::{fine_world_pos::FineWorldPos, size3::Size3, velocity::Velocity}, + geometry::rotation::SphericalRotation, +}; +use crate::{game::Game, scripts::player_belt_script::Belt}; + +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)] +#[wasm_bindgen] +pub struct Health { + pub health: u32, + pub max_health: u32, +} + +impl_component!(Health); + +#[wasm_bindgen] +pub struct Player { + entity: Entity, +} + +#[wasm_bindgen] +impl Player { + pub fn new(entity: Entity) -> Player { + Player { entity } + } + + pub fn make_entity(uid: EntityId) -> Entity { + let mut ent = Entity::new(uid, "player".to_string()); + ent.add::(FineWorldPos { + x: 0.0, + y: 10.0, + z: 0.0, + }); + ent.add::(Size3::new(0.8, 1.8, 0.8)); + ent.add::(Velocity::default()); + ent.add::(SphericalRotation::new(0.0, 0.0)); + ent.add::(None); + ent.add::(JumpData::default()); + ent.add::(Belt::default()); + ent.add::(GravityData { has_gravity: true }); + ent.add::(Forces::default()); + ent.add::(Health { + health: 100, + max_health: 100, + }); + ent + } + + pub fn is_player(entity: &Entity) -> bool { + entity.name == "player" + } + + #[wasm_bindgen(getter)] + pub fn dim(&self) -> Size3 { + self.entity.get::().unwrap().clone() + } + + #[wasm_bindgen(getter)] + pub fn pos(&self) -> FineWorldPos { + self.entity.get::().unwrap().clone() + } + + #[wasm_bindgen(getter)] + pub fn vel(&self) -> Velocity { + self.entity.get::().unwrap().clone() + } + + #[wasm_bindgen(getter)] + pub fn rot(&self) -> SphericalRotation { + self.entity.get::().unwrap().clone() + } + + #[wasm_bindgen(getter)] + pub fn belt(&self) -> Belt { + self.entity.get::().unwrap().clone() + } + + #[wasm_bindgen(getter)] + pub fn moving_direction(&self) -> MovingDirection { + self.entity.get::().unwrap().clone() + } + + #[wasm_bindgen(getter)] + pub fn health(&self) -> Health { + self.entity.get::().unwrap().clone() + } +} + +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "makeAndAddPlayer")] + pub fn make_and_add_player_wasm(&mut self, uid: EntityId) -> () { + // skip if player already exists + if self.entities.get_entity_by_id(uid).is_some() { + return; + } + let player = Player::make_entity(uid); + self.schedule_entity_insert(player); + } +} diff --git a/lib/world/src/entities/projectile.rs b/lib/world/src/entities/projectile.rs new file mode 100644 index 0000000..d1c02ba --- /dev/null +++ b/lib/world/src/entities/projectile.rs @@ -0,0 +1,25 @@ +struct FireballEntity { + pos: FineWorldPos, + vel: Velocity, + life: u8, +} + +#[wasm_bindgen] +#[derive(Clone, Deserialize, Serialize)] +struct Projectile { + pos: FineWorldPos, +} + +impl Entity for Projectile { + fn update(&mut self, world: &World) -> () { + todo!() + } + + fn perform_action(&mut self, action: EntityAction) -> () { + todo!() + } + + fn id(&self) -> u32 { + todo!() + } +} diff --git a/lib/world/src/game.rs b/lib/world/src/game.rs new file mode 100644 index 0000000..a030409 --- /dev/null +++ b/lib/world/src/game.rs @@ -0,0 +1,508 @@ +use crate::{ + chunk::{ + chunk::{Chunk, ChunkId}, + chunk_fetcher::ChunkFetcher, + chunk_pos::ChunkPos, + }, + components::world_pos::WorldPos, + entities::{ + entities::Entities, + entity::{Entity, EntityId}, + entity_action::{EntityActionDtoMaker, EntityActionHolder}, + fireball::FireballScript, + }, + scripts::{ + game_script::GameScripts, + player_belt_script::{SecondaryBeltAction, SelectItemAction, UsePrimaryItemAction}, + player_gravity_script::GravityScript, + player_jump_script::JumpAction, + player_move_script::{MoveAction, MoveScript}, + player_rot_script::RotateAction, + player_tp_script::TeleportAction, + velocity_script::VelocityScript, + }, + terrain_gen::TerrainGenerator, + utils::js_log, + world::{world_block::WorldBlock, World}, +}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; + +#[wasm_bindgen(getter_with_clone)] +#[derive(Serialize, Deserialize)] +pub struct CreateGameOptions { + pub name: String, + #[wasm_bindgen(js_name = "flatWorld")] + pub flat_world: bool, + #[wasm_bindgen(js_name = "flatWorldHeight")] + pub flat_world_height: i32, + #[wasm_bindgen(js_name = "debugWorld")] + pub debug_world: bool, + pub seed: u32, +} + +#[wasm_bindgen] +impl CreateGameOptions { + #[wasm_bindgen(constructor)] + pub fn new( + name: String, + flat_world: bool, + flat_world_height: i32, + debug_world: bool, + seed: u32, + ) -> CreateGameOptions { + CreateGameOptions { + name, + flat_world, + flat_world_height, + debug_world, + seed, + } + } + + pub fn default() -> CreateGameOptions { + CreateGameOptions { + name: "".to_string(), + flat_world: false, + flat_world_height: 1, + debug_world: false, + seed: 0, + } + } + + pub fn from_js(value: JsValue) -> Result { + serde_wasm_bindgen::from_value(value) + } + + pub fn to_js(&self) -> Result { + serde_wasm_bindgen::to_value(self) + } +} + +#[wasm_bindgen(getter_with_clone)] +pub struct Game { + pub name: String, + pub id: String, + pub world: World, + pub entities: Entities, + pub chunk_fetcher: ChunkFetcher, + #[wasm_bindgen(skip)] + pub scripts: GameScripts, + schedule: GameSchedule, + #[wasm_bindgen(skip)] + pub action_holder: EntityActionHolder, +} + +#[wasm_bindgen] +impl Game { + fn add_default_scripts(&mut self) { + js_log("Adding Default Scripts"); + self.scripts.ensure_script(MoveScript::name()); + self.scripts.ensure_script(VelocityScript::name()); + self.scripts.ensure_script(GravityScript::name()); + self.scripts.ensure_script(FireballScript::name()); + + self.action_holder.add_handler(MoveAction::make_handler()); + self.action_holder.add_handler(JumpAction::make_handler()); + self.action_holder.add_handler(RotateAction::make_handler()); + self.action_holder + .add_handler(UsePrimaryItemAction::make_handler()); + self.action_holder + .add_handler(SecondaryBeltAction::make_handler()); + self.action_holder + .add_handler(SelectItemAction::make_handler()); + self.action_holder + .add_handler(TeleportAction::make_handler()); + } + + #[wasm_bindgen(constructor)] + pub fn new() -> Game { + console_error_panic_hook::set_once(); + let mut g = Game { + name: "".to_string(), + id: Uuid::new_v4().to_string(), + world: World::default(), + entities: Entities::new(), + chunk_fetcher: ChunkFetcher::make_from_terrain_generator(TerrainGenerator::default()), + scripts: GameScripts::default(), + schedule: GameSchedule::empty(), + action_holder: EntityActionHolder::default(), + }; + g.add_default_scripts(); + g + } + + #[wasm_bindgen(js_name = "create")] + pub fn create(options: CreateGameOptions) -> Game { + let mut g = Game::new(); + g.name = options.name; + g.chunk_fetcher = ChunkFetcher::make_from_terrain_generator(TerrainGenerator::new( + options.seed, + options.flat_world, + options.flat_world_height, + options.debug_world, + )); + g.add_default_scripts(); + g + } + + pub fn build( + id: Option, + name: Option, + world: Option, + entities: Option, + scripts: Option, + chunk_fetcher: Option, + ) -> Game { + console_error_panic_hook::set_once(); + js_log("Building the game"); + let mut game = Game::new(); + if let Some(id) = id { + game.id = id; + } + if let Some(name) = name { + game.name = name; + } + if let Some(world) = world { + game.world = world; + } + if let Some(entities) = entities { + game.entities = entities; + } + if let Some(scripts) = scripts { + game.scripts = scripts; + } + if let Some(chunk_fetcher) = chunk_fetcher { + game.chunk_fetcher = chunk_fetcher; + } + game.add_default_scripts(); + game + } + + pub fn handle_actions(&mut self) { + let schedule = self + .action_holder + .handle_actions(&self.world, &mut self.entities); + self.schedule.combine(schedule); + } + + pub fn add_all_scripts(&mut self) { + self.scripts + .add_all_scheduled_scripts(&self.world, &self.entities, &mut self.chunk_fetcher); + } + + pub fn run_scripts(&mut self, delta_ms: f32) { + let world = &self.world; + for script in self.scripts.get_scripts_mut() { + let query = script.get_query(); + let query_results = self.entities.query(&query); + let diff = script.update(world, query_results, &mut self.chunk_fetcher, delta_ms); + if let Some(diff) = diff { + self.schedule.combine(diff); + } + } + } + + pub fn add_new_entities(&mut self) { + let new_ents = std::mem::take(&mut self.schedule.new_entities); + + // Tell the scripts about the new entities + self.scripts.iter_mut().for_each(|script| { + for entity in new_ents.iter() { + script.on_entity_update(entity.id); + } + }); + + self.entities.get_all_mut().extend(new_ents); + self.schedule.new_entities.clear(); + } + + pub fn remove_entities(&mut self) { + for entity_id in self.schedule.removed_entities.clone() { + self.entities + .get_all_mut() + .retain(|entity| entity.id != entity_id); + + self.scripts.iter_mut().for_each(|script| { + script.on_entity_update(entity_id); + }); + } + self.schedule.removed_entities.clear(); + } + + pub fn add_single_chunk(&mut self) { + let chunk = self.chunk_fetcher.consume_single_chunk(); + if let Some(chunk) = chunk { + let chunk_id = chunk.get_id(); + self.world.insert_chunk(chunk); + self.scripts.iter_mut().for_each(|script| { + script.on_chunk_update(chunk_id); + }); + } + } + + pub fn request_chunk(&mut self, chunk_pos: ChunkPos) { + self.chunk_fetcher.request_chunk(chunk_pos); + } + + pub fn add_blocks(&mut self) { + let new_blocks = std::mem::take(&mut self.schedule.new_blocks); + for block in new_blocks { + self.world.add_block(&block).unwrap(); + self.scripts.iter_mut().for_each(|script| { + let chunk_id = block.world_pos.to_chunk_pos().to_id(); + script.on_chunk_update(chunk_id); + }); + } + self.schedule.new_blocks.clear(); + } + + pub fn remove_blocks(&mut self) { + let removed_blocks = std::mem::take(&mut self.schedule.removed_blocks); + for block_pos in removed_blocks { + self.world.remove_block(&block_pos).unwrap(); + self.scripts.iter_mut().for_each(|script| { + let chunk_id = block_pos.to_chunk_pos().to_id(); + script.on_chunk_update(chunk_id); + }); + } + self.schedule.removed_blocks.clear(); + } + + pub fn update(&mut self, delta_ms: f32) { + self.handle_actions(); + self.add_all_scripts(); + self.run_scripts(delta_ms); + self.add_new_entities(); + self.remove_entities(); + // TODO: this shouldn't be async + self.add_single_chunk(); + self.add_blocks(); + self.remove_blocks(); + } + + pub fn schedule_chunk_insert(&mut self, chunk: Chunk) { + self.schedule.new_chunks.push(chunk) + } + + pub fn schedule_entity_insert(&mut self, entity: Entity) { + self.schedule.new_entities.push(entity); + } +} + +#[derive(Clone, Serialize, Deserialize)] +#[wasm_bindgen(getter_with_clone)] +pub struct GameDiff { + pub updated_entities: Vec, + pub updated_chunks: Vec, +} + +#[wasm_bindgen] +impl GameDiff { + #[wasm_bindgen(constructor)] + pub fn new() -> GameDiff { + GameDiff { + updated_entities: Vec::new(), + updated_chunks: Vec::new(), + } + } + + pub fn add_entity(&mut self, entity_id: EntityId) { + self.updated_entities.push(entity_id); + } + + pub fn add_chunk(&mut self, chunk_id: ChunkId) { + self.updated_chunks.push(chunk_id); + } + + pub fn to_js(&self) -> Result { + serde_wasm_bindgen::to_value(self) + } +} + +pub struct GameSchedule { + pub new_entities: Vec, + pub new_blocks: Vec, + pub new_chunks: Vec, + pub removed_entities: Vec, + pub removed_blocks: Vec, +} + +impl GameSchedule { + pub fn empty() -> GameSchedule { + GameSchedule { + new_entities: Vec::new(), + new_blocks: Vec::new(), + new_chunks: Vec::new(), + removed_entities: Vec::new(), + removed_blocks: Vec::new(), + } + } + + pub fn clear(&mut self) { + self.new_entities.clear(); + self.new_blocks.clear(); + self.new_chunks.clear(); + self.removed_entities.clear(); + self.removed_blocks.clear(); + } + + pub fn consume_single_chunk(&mut self) -> Option { + self.new_chunks.pop() + } + + pub fn to_game_diff(&self) -> GameDiff { + let mut updated_entities: Vec = + self.new_entities.iter().map(|entity| entity.id).collect(); + updated_entities.extend(self.removed_entities.iter().map(|entity_id| entity_id)); + + let mut updated_chunks: Vec = Vec::new(); + for block in self.new_blocks.iter() { + let chunk_pos = block.world_pos.to_chunk_pos(); + if !updated_chunks.contains(&chunk_pos.to_id()) { + updated_chunks.push(chunk_pos.to_id()); + } + } + for block_pos in self.removed_blocks.iter() { + let chunk_pos = block_pos.to_chunk_pos(); + if !updated_chunks.contains(&chunk_pos.to_id()) { + updated_chunks.push(chunk_pos.to_id()); + } + } + for new_chunk in self.new_chunks.iter() { + if !updated_chunks.contains(&new_chunk.get_id()) { + updated_chunks.push(new_chunk.get_id()); + } + } + + GameDiff { + updated_entities, + updated_chunks, + } + } + + pub fn combine(&mut self, other: GameSchedule) { + self.new_entities.extend(other.new_entities); + self.new_blocks.extend(other.new_blocks); + self.new_chunks.extend(other.new_chunks); + self.removed_entities.extend(other.removed_entities); + self.removed_blocks.extend(other.removed_blocks); + } + + pub fn add_entity(&mut self, entity: Entity) { + self.new_entities.push(entity) + } + + pub fn add_block(&mut self, block: WorldBlock) { + self.new_blocks.push(block); + } + + pub fn remove_block(&mut self, block_pos: WorldPos) { + self.removed_blocks.push(block_pos); + } + + pub fn add_chunk(&mut self, chunk: Chunk) { + self.new_chunks.push(chunk); + } + + pub fn remove_entity(&mut self, entity_id: EntityId) { + self.removed_entities.push(entity_id); + } +} + +#[cfg(test)] +mod tests { + use crate::{ + components::{fine_world_pos::FineWorldPos, velocity::Velocity}, + entities::player::Player, + geometry::direction::Direction, + scripts::{player_jump_script::JumpActionData, player_move_script::MoveActionData}, + }; + + use super::*; + const TEST_DELTA_MS: f32 = 16.67; + + #[test] + pub fn add_player() { + let mut game = Game::new(); + let player = Player::make_entity(1); + game.schedule_entity_insert(player); + game.update(TEST_DELTA_MS); + + // expect game to have a player in it + game.entities.get_all_mut().iter().for_each(|ent| { + assert_eq!(ent.id, 1); + }); + } + + #[test] + pub fn jump_script() { + let mut game = Game::new(); + let player = Player::make_entity(1); + game.schedule_entity_insert(player); + game.update(TEST_DELTA_MS); + let jump_action_handler = JumpAction::make_handler(); + game.action_holder.add_handler(jump_action_handler); + let jump_action = JumpAction::make_dto(1, JumpActionData {}); + game.action_holder.add(jump_action); + game.update(TEST_DELTA_MS); + let player = game.entities.get_entity_by_id(1).unwrap(); + let player_vel = player.get::().unwrap(); + assert!(player_vel.y > 0.0); + } + + #[test] + pub fn move_script() { + let mut game = Game::new(); + let player = Player::make_entity(1); + player.print_components(); + + game.schedule_entity_insert(player); + game.update(TEST_DELTA_MS); + + let move_script = Box::new(MoveScript::default()); + game.scripts.schedule_script_for_mount(move_script); + game.update(TEST_DELTA_MS); + + let velocity_script = Box::new(VelocityScript::default()); + game.scripts.schedule_script_for_mount(velocity_script); + game.update(TEST_DELTA_MS); + + game.action_holder.add_handler(MoveAction::make_handler()); + + let move_action = MoveAction::make_dto( + 1, + MoveActionData { + direction: Some(Direction::North), + }, + ); + game.action_holder.add(move_action); + game.update(TEST_DELTA_MS); + + let player = game.entities.get_entity_by_id(1).unwrap(); + let player_pos = player.get::().unwrap(); + assert!(player_pos.z > 0.0); + } + + // #[test] + // pub fn generate_chunk() { + // let mut game = Game::new(); + // let player = make_player(1); + // game.schedule_entity_insert(player); + // game.update(); + + // let sandbox_game_script = Box::new(SandBoxGScript::default()); + // game.add_script(sandbox_game_script); + // game.update(); + + // // Check that chunks loaded + // let chunk_count = game.world.chunk_count(); + // assert_eq!(chunk_count, 1); + + // game.update(); + + // let chunk_count = game.world.chunk_count(); + // assert_eq!(chunk_count, 2); + // } +} diff --git a/lib/world/src/direction.rs b/lib/world/src/geometry/direction.rs similarity index 59% rename from lib/world/src/direction.rs rename to lib/world/src/geometry/direction.rs index b5b3d0d..320ab50 100644 --- a/lib/world/src/direction.rs +++ b/lib/world/src/geometry/direction.rs @@ -1,4 +1,6 @@ -use crate::geometry::rotation::SphericalRotation; +use crate::geometry::vec::Vector3Ops; +use crate::geometry::{rotation::SphericalRotation, vec2::Vec2Ops}; +use num::One; use serde::{Deserialize, Serialize}; use std::{ f32::consts::PI, @@ -62,10 +64,21 @@ pub const EVERY_DIRECTION: [Direction; 6] = [ ]; #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[wasm_bindgen] pub struct Directions { data: [bool; 6], } +#[wasm_bindgen] +impl Directions { + pub fn to_array(&self) -> Vec { + (0..6) + .filter_map(|i| if self.data[i] { Some(i) } else { None }) + .map(move |i| Direction::from_index(i)) + .collect::>() + } +} + impl FromIterator for Directions { fn from_iter>(iter: I) -> Self { let mut data = [false; 6]; @@ -195,3 +208,87 @@ impl Into for Direction { } } } + +pub trait DirectionVectorExtension: Vector3Ops { + fn get_component_from_direction(&self, direction: Direction) -> Self::Scalar { + match direction { + Direction::North => self.z(), + Direction::South => self.z(), + Direction::East => self.x(), + Direction::West => self.x(), + Direction::Up => self.y(), + Direction::Down => self.y(), + } + } + + fn get_opposite_components_from_direction( + &self, + direction: Direction, + ) -> (Self::Scalar, Self::Scalar) { + match direction { + Direction::North => (self.x(), self.y()), + Direction::South => (self.x(), self.y()), + Direction::East => (self.y(), self.z()), + Direction::West => (self.y(), self.z()), + Direction::Up => (self.x(), self.z()), + Direction::Down => (self.x(), self.z()), + } + } + + fn get_component_from_axis(&self, axis: Axis) -> Self::Scalar { + match axis { + Axis::X => self.x(), + Axis::Y => self.y(), + Axis::Z => self.z(), + } + } + + fn set_component_from_axis(&mut self, axis: Axis, val: Self::Scalar) { + match axis { + Axis::X => self.set_x(val), + Axis::Y => self.set_y(val), + Axis::Z => self.set_z(val), + } + } + + fn move_direction(&self, direction: &Direction) -> Self { + let mut new_vec = self.copy(); + match direction { + Direction::North => new_vec.set_z(new_vec.z() + One::one()), + Direction::South => new_vec.set_z(new_vec.z() - One::one()), + Direction::East => new_vec.set_x(new_vec.x() + One::one()), + Direction::West => new_vec.set_x(new_vec.x() - One::one()), + Direction::Up => new_vec.set_y(new_vec.y() + One::one()), + Direction::Down => new_vec.set_y(new_vec.y() - One::one()), + } + new_vec + } + + fn move_in_flat_direction(&self, direction: &FlatDirection) -> Self { + let mut new_vec = self.copy(); + match direction { + FlatDirection::North => new_vec.set_y(new_vec.y() + One::one()), + FlatDirection::South => new_vec.set_y(new_vec.y() - One::one()), + FlatDirection::East => new_vec.set_x(new_vec.x() + One::one()), + FlatDirection::West => new_vec.set_x(new_vec.x() - One::one()), + } + new_vec + } +} + +impl DirectionVectorExtension for V {} + +pub trait DirectionVectorExtension2: Vec2Ops { + fn move_in_flat_direction(&self, direction: &FlatDirection) -> Self { + let mut new_vec = self.copy(); + match direction { + FlatDirection::North => new_vec.set_y(new_vec.y() + One::one()), + FlatDirection::South => new_vec.set_y(new_vec.y() - One::one()), + FlatDirection::East => new_vec.set_x(new_vec.x() + One::one()), + FlatDirection::West => new_vec.set_x(new_vec.x() - One::one()), + } + new_vec + } +} + +impl DirectionVectorExtension2 for V {} diff --git a/lib/world/src/geometry/line_segment.rs b/lib/world/src/geometry/line_segment.rs index 799feaf..1a88ec7 100644 --- a/lib/world/src/geometry/line_segment.rs +++ b/lib/world/src/geometry/line_segment.rs @@ -1,5 +1,7 @@ use crate::{ - chunk::chunk_mesh::BlockMesh, plane::WorldPlane, positions::FineWorldPos, world::World, + chunk::chunk_mesh::BlockMesh, components::fine_world_pos::FineWorldPos, + geometry::direction::DirectionVectorExtension, geometry::plane::WorldPlane, + geometry::vec::Vector3Ops, world::World, }; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; @@ -10,7 +12,7 @@ pub struct LineSegment { pub end_pos: FineWorldPos, } -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct LineSegmentIntersectionInfo { pub intersection_point: FineWorldPos, pub world_plane: WorldPlane, @@ -19,7 +21,7 @@ pub struct LineSegmentIntersectionInfo { impl LineSegment { pub fn length(&self) -> f32 { - self.start_pos.distance_to(self.end_pos) + self.start_pos.distance_to(&self.end_pos) } pub fn find_intersection(&self, plane: &WorldPlane) -> Option { @@ -50,9 +52,9 @@ impl LineSegment { // println!("t: {}", t); - let slope = self.end_pos - self.start_pos; - let scaled_slope = slope * t; - let intersection_point = self.start_pos + scaled_slope; + let slope = self.end_pos.sub(&self.start_pos); + let scaled_slope = slope.scalar_mult(t); + let intersection_point = self.start_pos.add(&scaled_slope); // println!("Intersection Point: {:?}", intersection_point); @@ -74,7 +76,7 @@ impl LineSegment { .map(|intersection_point| LineSegmentIntersectionInfo { intersection_point, world_plane, - distance: self.start_pos.distance_to(intersection_point), + distance: self.start_pos.distance_to(&intersection_point), }) }) // log the values @@ -96,7 +98,7 @@ impl LineSegment { Some(Ordering::Equal) | None => { // handle by comparing plane centers let plane_center_dist = |info: &LineSegmentIntersectionInfo| { - let dist = info.world_plane.get_center().distance_to(self.start_pos); + let dist = info.world_plane.get_center().distance_to(&self.start_pos); println!("line->block_mesh plane dist: {:?}", dist); dist }; @@ -129,9 +131,16 @@ impl World { // println!("Length: {}", line_segment.length()); // println!("Length: {}", (line_segment.length() + 1.0) as i32); - for n in 0..(line_segment.length() + 2.0) as i32 { - let slope = (line_segment.end_pos - line_segment.start_pos).set_mag(1.0); - let marched_pos = line_segment.start_pos + slope * n as f32; + // Use smaller step size to catch more intersections, especially near block boundaries + let step_size = 0.25; + let num_steps = ((line_segment.length() / step_size) + 2.0) as i32; + + for n in 0..num_steps { + let slope = line_segment + .end_pos + .sub(&line_segment.start_pos) + .set_mag(step_size); + let marched_pos = line_segment.start_pos.add(&slope.scalar_mult(n as f32)); // println!("Marched Pos: {:?}", marched_pos); // println!("Slope: {:?}", slope); @@ -178,12 +187,13 @@ impl World { #[cfg(test)] pub mod tests { use crate::{ - chunk::{chunk_mesh::BlockMesh, Chunk}, - direction::{Direction, Directions}, - plane::WorldPlane, - positions::{FineWorldPos, WorldPos}, - vec::Vec3, - world::World, + chunk::chunk_mesh::BlockMesh, + components::{fine_world_pos::FineWorldPos, world_pos::WorldPos}, + geometry::{ + direction::{Direction, Directions}, + plane::WorldPlane, + vec::Vector3Ops, + }, }; use super::{LineSegment, LineSegmentIntersectionInfo}; @@ -205,8 +215,8 @@ pub mod tests { }; let line_segment = LineSegment { - start_pos: Vec3::new(0.5, 0.0, 0.5), - end_pos: Vec3::new(0.5, 1.5, 0.5), + start_pos: FineWorldPos::new(0.5, 0.0, 0.5), + end_pos: FineWorldPos::new(0.5, 1.5, 0.5), }; let expect_intersection = FineWorldPos { x: 0.5, @@ -221,8 +231,8 @@ pub mod tests { }; let line_segment = LineSegment { - start_pos: Vec3::new(0.2, 0.5, 0.2), - end_pos: Vec3::new(0.4, -0.5, 0.4), + start_pos: FineWorldPos::new(0.2, 0.5, 0.2), + end_pos: FineWorldPos::new(0.4, -0.5, 0.4), }; let expect_intersection = FineWorldPos { x: 0.3, @@ -237,8 +247,8 @@ pub mod tests { }; let line_segment = LineSegment { - start_pos: Vec3::new(0.2, 0.5, 0.2), - end_pos: Vec3::new(0.4, -0.5, 0.4), + start_pos: FineWorldPos::new(0.2, 0.5, 0.2), + end_pos: FineWorldPos::new(0.4, -0.5, 0.4), }; let expect_intersection = None; run_line_segment_test(plane, line_segment, expect_intersection); @@ -248,8 +258,8 @@ pub mod tests { direction: Direction::East, }; let line_segment = LineSegment { - start_pos: Vec3::new(0.5, 0.5, 0.5), - end_pos: Vec3::new(1.5, 0.5, 0.5), + start_pos: FineWorldPos::new(0.5, 0.5, 0.5), + end_pos: FineWorldPos::new(1.5, 0.5, 0.5), }; let expect_intersection = FineWorldPos { x: 1.0, @@ -267,8 +277,8 @@ pub mod tests { direction: Direction::South, }, LineSegment { - start_pos: Vec3::new(-1.5, 0.5, -1.9), - end_pos: Vec3::new(-1.5, 0.5, -2.1), + start_pos: FineWorldPos::new(-1.5, 0.5, -1.9), + end_pos: FineWorldPos::new(-1.5, 0.5, -2.1), }, Some(FineWorldPos { x: -1.5, @@ -286,8 +296,8 @@ pub mod tests { direction: Direction::South, }, LineSegment { - start_pos: Vec3::new(-1.5, 0.5, -3.0), - end_pos: Vec3::new(-1.5, 0.5, -1.0), + start_pos: FineWorldPos::new(-1.5, 0.5, -3.0), + end_pos: FineWorldPos::new(-1.5, 0.5, -1.0), }, Some(FineWorldPos { x: -1.5, @@ -309,8 +319,8 @@ pub mod tests { #[test] fn find_intersection_with_blockmesh() { let line_segment = LineSegment { - start_pos: Vec3::new(0.5, 0.0, 0.5), - end_pos: Vec3::new(0.5, 1.5, 0.5), + start_pos: FineWorldPos::new(0.5, 0.0, 0.5), + end_pos: FineWorldPos::new(0.5, 1.5, 0.5), }; let block_mesh = BlockMesh { @@ -323,8 +333,8 @@ pub mod tests { run_blockmesh_test(line_segment, block_mesh, expect_intersection_info); let line_segment = LineSegment { - start_pos: Vec3::new(0.5, 2.0, 0.5), - end_pos: Vec3::new(0.5, -1.0, 0.5), + start_pos: FineWorldPos::new(0.5, 2.0, 0.5), + end_pos: FineWorldPos::new(0.5, -1.0, 0.5), }; let block_mesh = BlockMesh { diff --git a/lib/world/src/geometry/mod.rs b/lib/world/src/geometry/mod.rs index 4b92387..6f680e2 100644 --- a/lib/world/src/geometry/mod.rs +++ b/lib/world/src/geometry/mod.rs @@ -1,4 +1,8 @@ +pub mod direction; pub mod line_segment; +pub mod plane; pub mod ray; pub mod rect3; pub mod rotation; +pub mod vec; +pub mod vec2; diff --git a/lib/world/src/plane.rs b/lib/world/src/geometry/plane.rs similarity index 85% rename from lib/world/src/plane.rs rename to lib/world/src/geometry/plane.rs index 8505fa2..877a776 100644 --- a/lib/world/src/plane.rs +++ b/lib/world/src/geometry/plane.rs @@ -1,16 +1,15 @@ +use crate::components::{fine_world_pos::FineWorldPos, world_pos::WorldPos}; +use crate::geometry::direction::{Direction, DirectionVectorExtension}; use serde::{Deserialize, Serialize}; -use crate::{ - direction::Direction, - positions::{FineWorldPos, WorldPos}, -}; - #[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)] pub struct WorldPlane { pub world_pos: WorldPos, pub direction: Direction, } +const DISTANCE_EPSILON: f32 = 0.0001; + impl WorldPlane { pub fn new(world_pos: WorldPos, direction: Direction) -> WorldPlane { WorldPlane { @@ -57,9 +56,11 @@ impl WorldPlane { // their_x, their_y, their_z // ); - let contains_y = (my_y as f32 - their_y).abs() < 0.01; - let contains_x = (my_x as f32) - 0.01 <= their_x && my_x as f32 + 1.01 >= their_x; - let contains_z = (my_z as f32) - 0.01 <= their_z && my_z as f32 + 1.01 >= their_z; + let contains_y = (my_y as f32 - their_y).abs() < DISTANCE_EPSILON; + let contains_x = (my_x as f32) - DISTANCE_EPSILON <= their_x + && my_x as f32 + 1.0 + DISTANCE_EPSILON >= their_x; + let contains_z = (my_z as f32) - DISTANCE_EPSILON <= their_z + && my_z as f32 + 1.0 + DISTANCE_EPSILON >= their_z; // println!( // "Contains x: {}, Contains y: {}, Contains z: {}", @@ -73,8 +74,8 @@ impl WorldPlane { #[cfg(test)] mod tests { use crate::{ - direction::Direction, - positions::{FineWorldPos, WorldPos}, + components::{fine_world_pos::FineWorldPos, world_pos::WorldPos}, + geometry::{direction::Direction, vec::Vector3Ops}, }; use super::WorldPlane; diff --git a/lib/world/src/geometry/ray.rs b/lib/world/src/geometry/ray.rs index 260193d..48b10be 100644 --- a/lib/world/src/geometry/ray.rs +++ b/lib/world/src/geometry/ray.rs @@ -1,10 +1,10 @@ use super::{line_segment::LineSegment, rotation::SphericalRotation}; use crate::{ chunk::chunk_mesh::BlockMesh, - direction::Direction, - plane::WorldPlane, - positions::FineWorldPos, - vec::Vec3, + components::fine_world_pos::FineWorldPos, + geometry::direction::{Direction, DirectionVectorExtension}, + geometry::plane::WorldPlane, + geometry::vec::Vector3Ops, world::{world_block::WorldBlock, World}, }; use serde::{Deserialize, Serialize}; @@ -25,27 +25,27 @@ pub struct LookingAt { /** * The block a camera is pointing at */ - block: WorldBlock, + pub block: WorldBlock, /** * The face of the block that is being looked at */ - face: Direction, + pub face: Direction, /** * How far the face is away from the camera */ - distance: f32, + pub distance: f32, } impl Ray { pub fn move_forward_mut(&mut self, amount: f32) { - let rot_vec: Vec3 = self.rot.into(); - self.pos = rot_vec.scalar_mult(amount) + let rot_vec = self.rot.get_unit_vector().scalar_mult(amount); + self.pos = FineWorldPos::new(rot_vec.x(), rot_vec.y(), rot_vec.z()); } pub fn move_forward(&self, amount: f32) -> Ray { - let rot_vec: Vec3 = self.rot.into(); + let rot_vec = self.rot.get_unit_vector(); Ray { - pos: self.pos.add_vec(rot_vec.scalar_mult(amount)), + pos: self.pos.add(&rot_vec.scalar_mult(amount)), rot: self.rot, } } @@ -69,17 +69,17 @@ impl Ray { // PlanePos[dim] = CameraPos[dim] + t * CameraRotation // t = (PlanePos[dim] - CameraPos[dim]) / CameraRotation - let rot_vec: Vec3 = self.rot.into(); + let rot_vec = self.rot.get_unit_vector(); let t = (plane.get_relative_y() as f32 - self.pos.get_component_from_direction(plane.direction)) / rot_vec.get_component_from_direction(plane.direction); // Now find the actual position - let intersect_pos = self.pos.add_vec(rot_vec.scalar_mult(t)); + let intersect_pos = self.pos.add(&rot_vec.scalar_mult(t)); if plane.contains(intersect_pos) { - Some(self.pos.distance_to(intersect_pos)) + Some(self.pos.distance_to(&intersect_pos)) } else { None } @@ -107,11 +107,12 @@ mod tests { use super::{LookingAt, Ray}; use crate::{ block::{BlockData, BlockType}, - chunk::{chunk_mesh::BlockMesh, Chunk}, - direction::{Direction, Directions}, + chunk::{chunk::Chunk, chunk_mesh::BlockMesh}, + components::{fine_world_pos::FineWorldPos, world_pos::WorldPos}, + geometry::direction::{Direction, Directions}, + geometry::plane::WorldPlane, geometry::rotation::SphericalRotation, - plane::WorldPlane, - positions::{FineWorldPos, WorldPos}, + geometry::vec::Vector3Ops, world::{world_block::WorldBlock, World}, }; diff --git a/lib/world/src/geometry/rect3.rs b/lib/world/src/geometry/rect3.rs index 2e7a5b1..68b0192 100644 --- a/lib/world/src/geometry/rect3.rs +++ b/lib/world/src/geometry/rect3.rs @@ -1,6 +1,11 @@ +use crate::components::fine_world_pos::FineWorldPos; +use crate::components::size3::Size3; +use crate::components::world_pos::WorldPos; +use crate::geometry::direction::DirectionVectorExtension; +use crate::geometry::vec::Vector3Ops; +use crate::world::World; + use super::line_segment::{LineSegment, LineSegmentIntersectionInfo}; -use crate::positions::WorldPos; -use crate::{positions::FineWorldPos, vec::Vec3, world::World}; use serde::{Deserialize, Serialize}; use serde_wasm_bindgen::{from_value, to_value}; use std::cmp::Ordering; @@ -10,12 +15,37 @@ use wasm_bindgen::JsValue; #[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] pub struct Rect3 { pub pos: FineWorldPos, - pub dim: Vec3, + pub dim: Size3, } -static DISTANCE_EPSILON: f32 = 0.03; +static DISTANCE_EPSILON: f32 = 0.01; impl Rect3 { + pub fn does_intersect(&self, other: &Rect3) -> bool { + // Axis-Aligned Bounding Box (AABB) intersection test + let self_min_x = self.pos.x; + let self_max_x = self.pos.x + self.dim.x; + let self_min_y = self.pos.y; + let self_max_y = self.pos.y + self.dim.y; + let self_min_z = self.pos.z; + let self_max_z = self.pos.z + self.dim.z; + + let other_min_x = other.pos.x; + let other_max_x = other.pos.x + other.dim.x; + let other_min_y = other.pos.y; + let other_max_y = other.pos.y + other.dim.y; + let other_min_z = other.pos.z; + let other_max_z = other.pos.z + other.dim.z; + + // Check for separation along each axis + !(self_max_x <= other_min_x + || self_min_x >= other_max_x + || self_max_y <= other_min_y + || self_min_y >= other_max_y + || self_max_z <= other_min_z + || self_min_z >= other_max_z) + } + pub fn get_all_points(&self) -> [FineWorldPos; 8] { let x = self.pos.x; let y = self.pos.y; @@ -96,7 +126,25 @@ impl Rect3 { } impl World { - fn get_moving_rect3_intersection_info( + pub fn get_rect3_intersection_infos( + &self, + rect: &Rect3, + end_pos: FineWorldPos, + ) -> Vec { + let diff = end_pos.sub(&rect.pos); + + let line_segments = rect.get_all_points().map(|point| LineSegment { + start_pos: point, + end_pos: point.add(&diff), + }); + + line_segments + .iter() + .filter_map(|seg| self.get_line_segment_intersection_info(*seg)) + .collect() + } + + pub fn get_moving_rect3_intersection_info( &self, rect: &Rect3, end_pos: FineWorldPos, @@ -106,13 +154,13 @@ impl World { rect, end_pos ); - let diff = end_pos - rect.pos; + let diff = end_pos.sub(&rect.pos); println!("diff: {:?}", diff); let line_segments = rect.get_all_points().map(|point| LineSegment { start_pos: point, - end_pos: point + diff, + end_pos: point.add(&diff), }); for segment in &line_segments { @@ -131,51 +179,86 @@ impl World { } pub fn move_rect3(&self, rect: &Rect3, end_pos: FineWorldPos) -> FineWorldPos { - let new_pos_from_info = |info: LineSegmentIntersectionInfo, end_pos: FineWorldPos| { - let hit_axis = info.world_plane.direction.to_axis(); - let mut new_pos = end_pos.clone(); - let outward = info.world_plane.direction.is_outward(); - let rect_dim_dir = rect.dim.get_component_from_axis(hit_axis); + // Handle multiple sequential collisions (e.g., hitting a wall then the ground) + let mut current_end_pos = end_pos; + let mut current_rect = *rect; - let eplison_diff = if outward { - DISTANCE_EPSILON - } else { - -(rect_dim_dir + DISTANCE_EPSILON) - }; + // loop 3 times to handle multiple collisions one for each axis + for _ in 0..3 { + // Check for collisions from current position to target + let intersections = self.get_rect3_intersection_infos(¤t_rect, current_end_pos); - let hit_plane_pos = info.world_plane.get_relative_y() as f32; + if intersections.is_empty() { + break; + } - let new_axis_pos = eplison_diff + hit_plane_pos; + // Calculate the intersection that would push the rect the least + let mut axis_diffs = Vec::new(); + for intersection in &intersections { + let hit_axis = intersection.world_plane.direction.to_axis(); + let outward = intersection.world_plane.direction.is_outward(); + let hit_plane_pos = intersection.world_plane.get_relative_y() as f32; - // println!( - // "outward: {}, eplison_diff: {}, hit_plane_pos: {}, new_axis_pos: {}", - // outward, eplison_diff, hit_plane_pos, new_axis_pos - // ); + let new_axis_pos = if outward { + hit_plane_pos + DISTANCE_EPSILON + } else { + let rect_dim_dir = current_rect.dim.get_component_from_axis(hit_axis); + hit_plane_pos - (rect_dim_dir + DISTANCE_EPSILON) + }; - new_pos.set_component_from_axis(hit_axis, new_axis_pos); - new_pos - }; + let current_end_pos_intersection_axis_val = + current_end_pos.get_component_from_axis(hit_axis); - let mut current_end_pos = end_pos; + let diff = new_axis_pos - current_end_pos_intersection_axis_val; - for _ in 0..3 { - let intersection = self.get_moving_rect3_intersection_info(rect, current_end_pos); - - if let Some(info) = intersection { - // unsafe { - // web_sys::console::log_2(&"intersection".into(), &to_value(&info).unwrap()) - // } - println!("intersection: {:?}", info); - - current_end_pos = new_pos_from_info(info, current_end_pos); - // unsafe { - // web_sys::console::log_2(&"new_pos".into(), &to_value(¤t_end_pos).unwrap()) - // } - println!("new_pos: {:?}", current_end_pos); - } else { - // If no intersection is found, break the loop + axis_diffs.push((hit_axis, diff, new_axis_pos)); + } + + let min_diff = axis_diffs + .iter() + .min_by(|a, b| a.1.abs().partial_cmp(&b.1.abs()).unwrap_or(Ordering::Equal)); + + if min_diff.is_none() { + // No valid intersection found, break out of the loop break; } + + let (hit_axis, _, new_axis_pos) = min_diff.unwrap(); + + // Push the rect! + current_end_pos.set_component_from_axis(*hit_axis, *new_axis_pos); + current_rect + .pos + .set_component_from_axis(*hit_axis, *new_axis_pos); + + // let intersections_string = intersections + // .iter() + // .map(|info| format!("\n {:?}", info)) + // .collect::>() + // .join(", "); + + // let axises_diff_string = axis_diffs + // .iter() + // .map(|(axis, diff, new_axis_pos)| { + // format!( + // "\n axis: {:?}, diff: {:?}, new_axis_pos: {:?}", + // axis, diff, new_axis_pos + // ) + // }) + // .collect::>() + // .join(", "); + + // js_log(&format!( + // "({:?}) hit_axis: {:?}, \naxises_diff: {}, \nintersections: {}, \nstart_pos: {:?}, \ntrying_to_go_to: {:?}, \ncurrent_rect_pos: {:?}, \ncurrent_end_pos: {:?}", + // iteration, + // hit_axis, + // axises_diff_string, + // intersections_string, + // rect.pos, + // end_pos, + // current_rect.pos, + // current_end_pos + // )); } current_end_pos @@ -227,9 +310,9 @@ pub mod tests { use crate::{ block::{BlockData, BlockType}, chunk::Chunk, + components::{fine_world_pos::FineWorldPos, size3::Size3, world_pos::WorldPos}, geometry::rect3::Rect3, - positions::{FineWorldPos, WorldPos}, - vec::Vec3, + geometry::vec::Vector3Ops, world::{world_block::WorldBlock, World}, }; @@ -298,7 +381,7 @@ pub mod tests { y: 2.3, z: 0.5, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, FineWorldPos { x: 0.5, @@ -327,7 +410,7 @@ pub mod tests { y: 2.3, z: 0.5, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, FineWorldPos { x: 0.5, @@ -356,7 +439,7 @@ pub mod tests { y: 1.3, z: 2.5, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, FineWorldPos { x: 0.5, @@ -381,7 +464,7 @@ pub mod tests { y: 1.3, z: -1.5, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, FineWorldPos { x: -3.5, @@ -410,7 +493,7 @@ pub mod tests { y: 1.5, z: -1.5, }, - dim: Vec3::new(0.8, 0.8, 0.8), + dim: Size3::new(0.8, 0.8, 0.8), }, FineWorldPos { x: 0.5, @@ -439,7 +522,7 @@ pub mod tests { y: 1.5, z: 0.5, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, FineWorldPos { x: 0.5, @@ -464,7 +547,7 @@ pub mod tests { y: 1.03, z: 0.023, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, FineWorldPos { x: 5.007, @@ -548,7 +631,7 @@ pub mod tests { y: 1.1, z: 0.5, }, - dim: Vec3::new(1.0, 2.0, 1.0), + dim: Size3::new(1.0, 2.0, 1.0), }, FineWorldPos { x: -0.3, @@ -584,7 +667,7 @@ pub mod tests { y: 1.3, z: -1.5, }, - dim: Vec3::new(0.8, 2.0, 0.8), + dim: Size3::new(0.8, 2.0, 0.8), }, FineWorldPos { x: -2.5, @@ -620,7 +703,7 @@ pub mod tests { y: 1.3, z: 1.9, }, - dim: Vec3::new(0.8, 2.0, 0.8), + dim: Size3::new(0.8, 2.0, 0.8), }, FineWorldPos { x: 2.3, @@ -649,7 +732,7 @@ pub mod tests { y: 1.1, z: 0.5, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, FineWorldPos { x: 0.3, @@ -664,6 +747,52 @@ pub mod tests { ); } + #[test] + fn test_cursed_movement() { + // test_try_moving_blocks( + // vec![ + // WorldBlock { + // block_type: BlockType::Leaf, + // extra_data: BlockData::None, + // world_pos: WorldPos::new(-15, 0, -24), + // }, + // WorldBlock { + // block_type: BlockType::Leaf, + // extra_data: BlockData::None, + // world_pos: WorldPos::new(-15, 0, -25), + // }, + // WorldBlock { + // block_type: BlockType::Leaf, + // extra_data: BlockData::None, + // world_pos: WorldPos::new(-14, 0, -24), + // }, + // WorldBlock { + // block_type: BlockType::Leaf, + // extra_data: BlockData::None, + // world_pos: WorldPos::new(-14, 0, -25), + // }, + // ], + // Rect3 { + // pos: FineWorldPos { + // x: -14.833749, + // y: 1.03, + // z: -25.27446, + // }, + // dim: Size3::new(1.0, 1.0, 1.0), + // }, + // FineWorldPos { + // x: -15.493927, + // y: 0.92999995, + // z: -24.523352, + // }, + // FineWorldPos { + // x: -15.493927, + // y: 1.03, + // z: -24.523352, + // }, + // ); + } + fn test_get_rect3_intersecting_blocks( block: WorldBlock, rect: Rect3, @@ -691,7 +820,7 @@ pub mod tests { y: 2.3, z: 0.5, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, vec![], ); @@ -711,7 +840,7 @@ pub mod tests { y: 0.5, z: 0.0, }, - dim: Vec3::new(1.0, 1.0, 1.0), + dim: Size3::new(1.0, 1.0, 1.0), }, vec![WorldPos::new(0, 0, 0)], ); diff --git a/lib/world/src/geometry/rotation.rs b/lib/world/src/geometry/rotation.rs index c98c703..55b2251 100644 --- a/lib/world/src/geometry/rotation.rs +++ b/lib/world/src/geometry/rotation.rs @@ -1,8 +1,13 @@ -use crate::vec::Vec3; +use crate::{ + components::{fine_world_pos::FineWorldPos, velocity::Velocity}, + entities::entity_component::impl_component, +}; use serde::{Deserialize, Serialize}; -use std::f32::consts::PI; +use std::{f32::consts::PI, ops::Add}; +use wasm_bindgen::prelude::wasm_bindgen; -#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize)] +#[wasm_bindgen] pub struct SphericalRotation { /** The flat angle. [0, 2PI] */ pub theta: f32, @@ -11,21 +16,85 @@ pub struct SphericalRotation { pub phi: f32, } +#[wasm_bindgen] +impl SphericalRotation { + pub fn new_wasm(theta: f32, phi: f32) -> SphericalRotation { + SphericalRotation { theta, phi } + } + + pub fn add(&self, other: &SphericalRotation) -> SphericalRotation { + *self + *other + } +} + +impl_component!(SphericalRotation); + impl SphericalRotation { pub fn new(theta: f32, phi: f32) -> SphericalRotation { SphericalRotation { theta, phi } } + + pub fn get_unit_vector(&self) -> Velocity { + let phi_offset = (PI / 2.0) - self.phi; + let theta_offset = self.theta + (PI / 2.0); + + Velocity::new( + -(theta_offset.cos() * phi_offset.sin()), + -phi_offset.cos(), + theta_offset.sin() * phi_offset.sin(), + ) + } + + pub fn to_fine_world_pos(&self) -> FineWorldPos { + let phi_offset = (PI / 2.0) - self.phi; + let theta_offset = self.theta + (PI / 2.0); + + FineWorldPos { + x: -(theta_offset.cos() * phi_offset.sin()), + y: -phi_offset.cos(), + z: theta_offset.sin() * phi_offset.sin(), + } + } +} + +impl Add for SphericalRotation { + type Output = Self; + + fn add(self, other: Self) -> Self { + // Add the angles + let mut new_theta = self.theta + other.theta; + let mut new_phi = self.phi + other.phi; + + // Ensure theta is in [0, 2PI] + if new_theta < 0.0 { + new_theta += 2.0 * std::f32::consts::PI; + } else if new_theta > 2.0 * std::f32::consts::PI { + new_theta -= 2.0 * std::f32::consts::PI; + } + + // Ensure phi is in [-PI/2, PI/2] + if new_phi < -std::f32::consts::FRAC_PI_2 { + new_phi = -std::f32::consts::FRAC_PI_2; + } else if new_phi > std::f32::consts::FRAC_PI_2 { + new_phi = std::f32::consts::FRAC_PI_2; + } + + Self { + theta: new_theta, + phi: new_phi, + } + } } -impl Into> for SphericalRotation { +impl Into for SphericalRotation { /** * Converts a spherical rotation into a unit vector. */ - fn into(self) -> Vec3 { + fn into(self) -> Velocity { let phi_offset = (PI / 2.0) - self.phi; let theta_offset = self.theta + (PI / 2.0); - Vec3 { + Velocity { x: -(theta_offset.cos() * phi_offset.sin()), y: -phi_offset.cos(), z: theta_offset.sin() * phi_offset.sin(), @@ -36,29 +105,29 @@ impl Into> for SphericalRotation { #[cfg(test)] mod tests { use super::*; - use crate::direction::Direction; + use crate::geometry::direction::Direction; - impl Vec3 { - fn assert_eq(&self, other: Vec3) { + impl Velocity { + fn assert_eq(&self, other: Velocity) { assert!((self.x - other.x).abs() < 0.0001); assert!((self.y - other.y).abs() < 0.0001); assert!((self.z - other.z).abs() < 0.0001); } } - fn run_direction_test(direction: Direction, expected: Vec3) { + fn run_direction_test(direction: Direction, expected: Velocity) { let rot: SphericalRotation = direction.into(); - let unit_vector: Vec3 = rot.into(); + let unit_vector: Velocity = rot.into(); unit_vector.assert_eq(expected); } #[test] fn tests_directions() { - run_direction_test(Direction::North, Vec3::new(0.0, 0.0, 1.0)); - run_direction_test(Direction::South, Vec3::new(0.0, 0.0, -1.0)); - run_direction_test(Direction::East, Vec3::new(1.0, 0.0, 0.0)); - run_direction_test(Direction::West, Vec3::new(-1.0, 0.0, 0.0)); - run_direction_test(Direction::Up, Vec3::new(0.0, 1.0, 0.0)); - run_direction_test(Direction::Down, Vec3::new(0.0, -1.0, 0.0)); + run_direction_test(Direction::North, Velocity::new(0.0, 0.0, 1.0)); + run_direction_test(Direction::South, Velocity::new(0.0, 0.0, -1.0)); + run_direction_test(Direction::East, Velocity::new(1.0, 0.0, 0.0)); + run_direction_test(Direction::West, Velocity::new(-1.0, 0.0, 0.0)); + run_direction_test(Direction::Up, Velocity::new(0.0, 1.0, 0.0)); + run_direction_test(Direction::Down, Velocity::new(0.0, -1.0, 0.0)); } } diff --git a/lib/world/src/geometry/vec.rs b/lib/world/src/geometry/vec.rs new file mode 100644 index 0000000..346f184 --- /dev/null +++ b/lib/world/src/geometry/vec.rs @@ -0,0 +1,224 @@ +use crate::geometry::direction::{DirectionVectorExtension, Directions}; +use num::{One, Zero}; +use std::{ + fmt::Display, + ops::{Div, Neg}, +}; + +pub trait AsF32 { + fn as_f32(self) -> f32; +} + +// Note: this might cut off the precision of bigger numbers +impl AsF32 for i32 { + fn as_f32(self) -> f32 { + self as f32 + } +} + +impl AsF32 for f32 { + fn as_f32(self) -> f32 { + self + } +} + +impl AsF32 for i16 { + fn as_f32(self) -> f32 { + self as f32 + } +} + +impl AsF32 for u8 { + fn as_f32(self) -> f32 { + self as f32 + } +} + +impl AsF32 for i8 { + fn as_f32(self) -> f32 { + self as f32 + } +} + +pub trait Vector3Ops: Sized { + type Scalar: Copy + + std::ops::Add + + std::ops::Sub + + std::ops::Mul + + std::ops::Div + + Display + + One + + Neg + + Zero + + AsF32 + + Copy; + + fn new(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self; + fn x(&self) -> Self::Scalar; + fn y(&self) -> Self::Scalar; + fn z(&self) -> Self::Scalar; + + fn set_x(&mut self, val: Self::Scalar); + fn set_y(&mut self, val: Self::Scalar); + fn set_z(&mut self, val: Self::Scalar); + + fn copy(&self) -> Self { + Self::new(self.x(), self.y(), self.z()) + } + + fn add(&self, other: &V) -> Self + where + V: Vector3Ops, + V::Scalar: Into, + Self::Scalar: std::ops::Add, + { + Self::new( + self.x() + other.x().into(), + self.y() + other.y().into(), + self.z() + other.z().into(), + ) + } + + fn sub>(&self, other: &V) -> Self { + Self::new( + self.x() - other.x(), + self.y() - other.y(), + self.z() - other.z(), + ) + } + + fn scalar_mult(&self, val: Self::Scalar) -> Self { + Self::new(self.x() * val, self.y() * val, self.z() * val) + } + + fn sqr(&self) -> Self { + Self::new( + self.x() * self.x(), + self.y() * self.y(), + self.z() * self.z(), + ) + } + + fn dot>(&self, other: &V) -> Self::Scalar { + self.x() * other.x() + self.y() * other.y() + self.z() * other.z() + } + + fn magnitude_squared(&self) -> Self::Scalar { + self.x() * self.x() + self.y() * self.y() + self.z() * self.z() + } + + fn get_mag(&self) -> f32 { + let x = self.x().as_f32(); + let y = self.y().as_f32(); + let z = self.z().as_f32(); + + (x * x + y * y + z * z).sqrt() + } + + fn sum(&self) -> Self::Scalar { + self.x() + self.y() + self.z() + } + + fn set_mag(&self, mag: Self::Scalar) -> Self + where + Self::Scalar: Into + From + Div, + { + let current_mag = self.get_mag(); + let scale: Self::Scalar = mag / current_mag; + self.scalar_mult(scale) + } + + fn distance_to(&self, vec: &U) -> f32 + where + U: Vector3Ops, + { + self.sub(vec).sqr().sum().as_f32().sqrt() + } + + fn map(&self, f: F) -> Self + where + F: Fn(Self::Scalar) -> Self::Scalar, + { + Self::new(f(self.x()), f(self.y()), f(self.z())) + } + + fn get_adjacent_vecs(&self) -> Vec { + let mut vecs = Vec::new(); + for direction in Directions::all() { + vecs.push(self.move_direction(&direction)); + } + vecs + } + + /** + * Like get_adjacent_vecs, but also returns the original vector + */ + fn get_cross_vecs(&self) -> Vec { + let mut vecs: Vec = Vec::new(); + vecs.push(self.copy()); + for direction in Directions::all() { + vecs.push(self.move_direction(&direction)); + } + vecs + } + + /** + * Returns all blocks in a cube around the vector + * I am not proud of this + */ + fn get_cube_vecs(&self) -> Vec { + let mut vecs: Vec = Vec::new(); + vecs.push(self.copy()); + let one = Self::Scalar::one(); + let zero = Self::Scalar::zero(); + for x in [-one, one, zero].iter().cloned() { + for y in [-one, one, zero].iter().cloned() { + for z in [-one, one, zero].iter().cloned() { + vecs.push(Self::new(self.x() + x, self.y() + y, self.z() + z)); + } + } + } + + vecs + } + + fn to_index(&self) -> String { + format!("{},{},{}", self.x(), self.y(), self.z()) + .as_str() + .to_owned() + } +} + +// Macro to implement common operations +macro_rules! impl_vector_ops { + ($vector_type:ident, $scalar_type:ty) => { + impl $crate::geometry::vec::Vector3Ops for $vector_type { + type Scalar = $scalar_type; + + fn new(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self { + Self { x, y, z } + } + + fn x(&self) -> Self::Scalar { + self.x + } + fn y(&self) -> Self::Scalar { + self.y + } + fn z(&self) -> Self::Scalar { + self.z + } + + fn set_x(&mut self, val: Self::Scalar) { + self.x = val + } + fn set_y(&mut self, val: Self::Scalar) { + self.y = val + } + fn set_z(&mut self, val: Self::Scalar) { + self.z = val + } + } + }; +} +pub(crate) use impl_vector_ops; diff --git a/lib/world/src/geometry/vec2.rs b/lib/world/src/geometry/vec2.rs new file mode 100644 index 0000000..3b88c0a --- /dev/null +++ b/lib/world/src/geometry/vec2.rs @@ -0,0 +1,93 @@ +use crate::geometry::vec::AsF32; +use num::{One, Zero}; +use std::{ + fmt::Display, + ops::{Add, Div, Mul, Neg, Sub}, +}; + +pub trait Vec2Ops: Sized { + type Scalar: Copy + + Add + + Sub + + Mul + + Div + + Neg + + Zero + + One + + AsF32 + + Display; + + fn new(x: Self::Scalar, y: Self::Scalar) -> Self; + + fn x(&self) -> Self::Scalar; + fn y(&self) -> Self::Scalar; + + fn set_x(&mut self, val: Self::Scalar); + fn set_y(&mut self, val: Self::Scalar); + + fn copy(&self) -> Self { + Self::new(self.x(), self.y()) + } + + fn add(&self, other: Self) -> Self { + return Self::new(self.x() + other.x(), self.y() + other.y()); + } + + fn sub(&self, other: &Self) -> Self { + return Self::new(self.x() - other.x(), self.y() - other.y()); + } + + fn scalar_mul(&self, other: Self::Scalar) -> Self { + return Self::new(self.x() * other, self.y() * other); + } + + fn mul(&self, other: Self::Scalar) -> Self { + return Self::new(self.x() * other, self.y() * other); + } + + fn div(&self, other: Self::Scalar) -> Self { + return Self::new(self.x() / other, self.y() / other); + } + + fn sqr(&self) -> Self { + return Self::new(self.x() * self.x(), self.y() * self.y()); + } + + fn sum(&self) -> Self::Scalar { + return self.x() + self.y(); + } + + fn distance_to(&self, other: &Self) -> f32 { + return self.sub(other).sqr().sum().as_f32().sqrt(); + } + + fn move_to_3d(&self, y_val: Self::Scalar) -> Self { + return Self::new(self.x(), y_val); + } +} + +macro_rules! impl_vec2_ops { + ($vector_type:ident, $scalar_type:ty) => { + impl $crate::geometry::vec2::Vec2Ops for $vector_type { + type Scalar = $scalar_type; + + fn new(x: Self::Scalar, y: Self::Scalar) -> Self { + Self { x, y } + } + + fn x(&self) -> Self::Scalar { + self.x + } + fn y(&self) -> Self::Scalar { + self.y + } + fn set_x(&mut self, val: Self::Scalar) { + self.x = val + } + fn set_y(&mut self, val: Self::Scalar) { + self.y = val + } + } + }; +} +pub(crate) use impl_vec2_ops; diff --git a/lib/world/src/lib.rs b/lib/world/src/lib.rs index 6323020..96a3ae6 100644 --- a/lib/world/src/lib.rs +++ b/lib/world/src/lib.rs @@ -1,11 +1,12 @@ pub mod block; pub mod chunk; -pub mod direction; +pub mod components; +pub mod entities; +pub mod game; pub mod geometry; -pub mod plane; -pub mod positions; -mod utils; -pub mod vec; +pub mod scripts; +pub mod terrain_gen; +pub mod utils; pub mod world; use wasm_bindgen::prelude::*; diff --git a/lib/world/src/positions.rs b/lib/world/src/positions.rs deleted file mode 100644 index de08e78..0000000 --- a/lib/world/src/positions.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::{ - chunk::CHUNK_WIDTH, - vec::{Vec2, Vec3}, -}; - -#[cfg(test)] -mod unit_tests; - -pub type InnerChunkPos = Vec3; -pub type WorldPos = Vec3; -pub type ChunkPos = Vec2; -pub type FineWorldPos = Vec3; - -impl InnerChunkPos { - pub fn to_chunk_index(&self) -> usize { - let x_part = (self.x as usize) << (4 + 6); - let y_part = (self.y as usize) << 4; - let z_part = self.z as usize; - x_part + y_part + z_part - } - - pub fn make_from_chunk_index(index: usize) -> InnerChunkPos { - let x_part = (index >> (4 + 6)) as u8; - let y_part = ((index & 0b1111110000) >> 4) as u8; - let z_part = (index & 0b1111) as u8; - InnerChunkPos::new(x_part, y_part, z_part) - } - - pub fn to_world_pos(&self, chunk_pos: &ChunkPos) -> WorldPos { - chunk_pos - .scalar_mul(CHUNK_WIDTH) - .move_to_3d(0) - .add_vec(self.map(|x| x as i16)) - .map(|x| x as i32) - } -} - -impl WorldPos { - pub fn is_valid(&self) -> bool { - self.y >= 0 && self.y < 256 - } - - pub fn to_inner_chunk_pos(&self) -> InnerChunkPos { - let x = (((self.x as i8 % 16) + 16) % 16) as u8; - let y = self.y as u8; - let z = (((self.z as i8 % 16) + 16) % 16) as u8; - InnerChunkPos::new(x, y, z) - } - - pub fn to_chunk_pos(&self) -> ChunkPos { - let x = if self.x < 0 { - ((self.x + 1) / CHUNK_WIDTH as i32) - 1 - } else { - self.x / CHUNK_WIDTH as i32 - }; - - let y = if self.z < 0 { - ((self.z + 1) / CHUNK_WIDTH as i32) - 1 - } else { - self.z / CHUNK_WIDTH as i32 - }; - - ChunkPos { - x: x as i16, - y: y as i16, - } - } -} - -impl ChunkPos { - pub fn to_world_index(&self) -> i32 { - let x = self.x as i32; - let y = self.y as i32; - x + (y << 16) - } -} - -impl FineWorldPos { - pub fn to_world_pos(&self) -> WorldPos { - WorldPos { - x: self.x as i32, - y: self.y as i32, - z: self.z as i32, - } - } - - pub fn round(&mut self) { - const PRECISION: f32 = 0.001; // Precision to three decimal places - self.x = (self.x / PRECISION).round() * PRECISION; - self.y = (self.y / PRECISION).round() * PRECISION; - self.z = (self.z / PRECISION).round() * PRECISION; - } - - pub fn equal(&self, other: &FineWorldPos) -> bool { - const PRECISION: f32 = 0.001; // Precision to three decimal places - - // Compare components with the specified precision - (self.x - other.x).abs() < PRECISION - && (self.y - other.y).abs() < PRECISION - && (self.z - other.z).abs() < PRECISION - } -} diff --git a/lib/world/src/positions/unit_tests.rs b/lib/world/src/positions/unit_tests.rs deleted file mode 100644 index 637ec20..0000000 --- a/lib/world/src/positions/unit_tests.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::positions::{ChunkPos, InnerChunkPos, WorldPos}; - -#[test] -fn index_conversion() { - fn do_test(index: usize, inner_chunk_pos: InnerChunkPos) -> () { - assert_eq!(inner_chunk_pos.to_chunk_index(), index); - assert_eq!(InnerChunkPos::make_from_chunk_index(index), inner_chunk_pos); - } - - do_test(1024 + 32 + 3, InnerChunkPos::new(1, 2, 3)); - do_test(0, InnerChunkPos::new(0, 0, 0)); -} - -#[test] -fn inner_chunk_pos_to_chunk_index() { - fn do_test(inner_chunk_pos: InnerChunkPos) { - let index = inner_chunk_pos.to_chunk_index(); - let inner_chunk_pos2 = InnerChunkPos::make_from_chunk_index(index); - assert_eq!(inner_chunk_pos, inner_chunk_pos2); - } - - do_test(InnerChunkPos::new(0, 0, 0)); - do_test(InnerChunkPos::new(15, 15, 15)); -} - -#[test] -fn inner_chunk_pos_to_world_pos() { - fn do_test(inner_chunk_pos: InnerChunkPos, chunk_pos: ChunkPos, world_pos: WorldPos) { - assert_eq!(inner_chunk_pos.to_world_pos(&chunk_pos), world_pos); - } - - do_test( - InnerChunkPos::new(1, 2, 3), - ChunkPos { x: 0, y: 0 }, - WorldPos { x: 1, y: 2, z: 3 }, - ); - - do_test( - InnerChunkPos::new(1, 2, 3), - ChunkPos { x: 1, y: 1 }, - WorldPos { x: 17, y: 2, z: 19 }, - ); - - do_test( - InnerChunkPos::new(1, 2, 3), - ChunkPos { x: -1, y: -1 }, - WorldPos { - x: -15, - y: 2, - z: -13, - }, - ); - - do_test( - InnerChunkPos::new(15, 0, 15), - ChunkPos { x: -2, y: -3 }, - WorldPos { - x: -17, - y: 0, - z: -33, - }, - ); -} - -#[test] -fn world_pos_to_chunk_pos() { - assert_eq!( - WorldPos { x: 1, y: 2, z: 3 }.to_chunk_pos(), - ChunkPos { x: 0, y: 0 } - ); - assert_eq!( - WorldPos { x: 0, y: 0, z: 0 }.to_chunk_pos(), - ChunkPos { x: 0, y: 0 } - ); - assert_eq!( - WorldPos { x: -1, y: 0, z: -1 }.to_chunk_pos(), - ChunkPos { x: -1, y: -1 } - ); - - assert_eq!( - WorldPos { - x: -16, - y: 0, - z: -16, - } - .to_chunk_pos(), - ChunkPos { x: -1, y: -1 } - ); - - assert_eq!( - WorldPos { x: 16, y: 0, z: 0 }.to_chunk_pos(), - ChunkPos { x: 1, y: 0 } - ); - - assert_eq!( - WorldPos { x: 0, y: 0, z: -1 }.to_chunk_pos(), - ChunkPos { x: 0, y: -1 } - ); -} - -#[test] -fn world_pos_to_inner_chunk_pos() { - assert_eq!( - WorldPos { x: 1, y: 2, z: 3 }.to_inner_chunk_pos(), - InnerChunkPos { x: 1, y: 2, z: 3 } - ); - - assert_eq!( - WorldPos { x: -1, y: 0, z: 1 }.to_inner_chunk_pos(), - InnerChunkPos { x: 15, y: 0, z: 1 } - ); - - assert_eq!( - WorldPos { x: -1, y: 0, z: -1 }.to_inner_chunk_pos(), - InnerChunkPos { x: 15, y: 0, z: 15 } - ); - - assert_eq!( - WorldPos { - x: -32, - y: 20, - z: 0, - } - .to_inner_chunk_pos(), - InnerChunkPos { x: 0, y: 20, z: 0 } - ); -} diff --git a/lib/world/src/scripts/game_script.rs b/lib/world/src/scripts/game_script.rs new file mode 100644 index 0000000..8d4081d --- /dev/null +++ b/lib/world/src/scripts/game_script.rs @@ -0,0 +1,528 @@ +use crate::chunk::chunk::ChunkId; +use crate::chunk::chunk_fetcher::ChunkFetcher; +use crate::entities::entities::{Entities, EntityQuery, EntityQueryResults}; +use crate::entities::entity::EntityId; +use crate::entities::fireball::FireballScript; +use crate::game::Game; +use crate::game::GameSchedule; +use crate::scripts::player_gravity_script::GravityScript; +use crate::scripts::player_move_script::MoveScript; +use crate::scripts::sandbox::SandBoxGScript; +use crate::scripts::velocity_script::VelocityScript; +use crate::utils::js_log; +use crate::world::World; +use js_sys::JSON; +use lazy_static::lazy_static; +use serde::ser::SerializeStruct; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_json::{from_value, to_value}; +use std::any::Any; +use std::cell::RefCell; +use std::collections::HashMap; +use std::fmt::Debug; +use std::sync::Mutex; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::{JsCast, JsValue}; + +pub trait GameScript: Any + Debug { + fn on_script_mounted( + &mut self, + _world: &World, + _entities: &Entities, + _chunk_fetcher: &mut ChunkFetcher, + ) { + // Default implementation does nothing + } + + fn update( + &mut self, + _world: &World, + _query_results: EntityQueryResults, + _chunk_fetcher: &mut ChunkFetcher, + _delta_ms: f32, + ) -> Option { + None + } + + fn get_name(&self) -> String { + "".to_string() + } + + fn get_config(&self) -> JsValue { + JsValue::null() + } + + fn set_config(&mut self, _config: JsValue) { + // Default implementation does nothing + } + + fn get_query(&self) -> EntityQuery { + EntityQuery::new() + } + + fn on_chunk_update(&self, _chunk_id: ChunkId) { + // Default implementation does nothing + } + + fn on_entity_update(&self, _entity_id: EntityId) { + // Default implementation does nothing + } + + fn get_state_wasm(&self) -> JsValue { + JsValue::null() + } + + fn set_state_wasm(&mut self, _val: JsValue) { + // no-op + } +} + +impl std::error::Error for ScriptNotFoundError {} + +#[derive(Debug)] +pub struct ScriptNotFoundError { + pub entity_id: EntityId, + pub script_name: String, +} + +impl std::fmt::Display for ScriptNotFoundError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Script '{}' not found for entity with ID {}", + self.script_name, self.entity_id + ) + } +} + +#[derive(Debug, Default)] +#[wasm_bindgen] +pub struct GameScripts { + scripts: Vec>, + scripts_to_add: Vec>, +} + +impl Clone for GameScripts { + fn clone(&self) -> Self { + js_log("cloning"); + let serial = to_value(self).unwrap(); + + from_value(serial).unwrap() + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct GameScriptSerial { + name: String, + config: String, +} + +impl Serialize for GameScripts { + fn serialize(&self, serializer: S) -> Result { + let mut s = serializer.serialize_struct("GameScripts", 1)?; + + let scripts: Vec<_> = self + .scripts + .iter() + .map(|s| { + let name = s.get_name(); + let js_config = s.get_config(); + let config: String = JSON::stringify(&js_config).unwrap().into(); + js_log(&format!( + "Serialize script: {:?} {:?} {:?}", + name, js_config, config + )); + + return GameScriptSerial { name, config }; + }) + .collect(); + + s.serialize_field("scripts", &scripts)?; + s.end() + } +} + +impl<'de> Deserialize<'de> for GameScripts { + fn deserialize>(deserializer: D) -> Result { + #[derive(Deserialize)] + struct GameScriptHelper { + scripts: Vec, + } + + let GameScriptHelper { scripts } = GameScriptHelper::deserialize(deserializer)?; + + let mut game_scripts = GameScripts { + scripts: vec![], + scripts_to_add: vec![], + }; + + for item in scripts { + let js_config: JsValue = JSON::parse(&item.config).unwrap(); + + js_log(&format!( + "Deserializing script {:?} with config {:?}", + item.name, js_config + )); + + let mut game_script = GameScripts::build_script_from_registry(item.name); + game_script.set_config(js_config); + game_scripts.add_script(game_script); + } + + Ok(game_scripts) + } +} + +impl GameScripts { + fn build_script_from_registry(script_name: String) -> Box { + if let Some(builder) = SCRIPT_REGISTRY.lock().unwrap().get(&script_name) { + return builder(); + } + + WASM_SCRIPT_REGISTERY.with(|reg| { + let map = reg.borrow(); + if let Some(builder) = map.get(&script_name) { + return (builder)(); + } + panic!("Script {:?} not found in registry", script_name); + }) + } + + pub fn schedule_script_for_mount(&mut self, script: Box) { + self.scripts_to_add.push(script); + } + + pub fn add_all_scheduled_scripts( + &mut self, + world: &World, + entities: &Entities, + chunk_fetcher: &mut ChunkFetcher, + ) { + let scripts = std::mem::take(&mut self.scripts_to_add); + for script in scripts { + let script_name = script.get_name(); + self.add_script(script); + let script = self.get_script_by_name_mut(script_name).unwrap(); + script.on_script_mounted(world, entities, chunk_fetcher); + } + } + + fn add_script(&mut self, script: Box) { + js_log(&format!("Adding script {}", script.get_name())); + let name = script.get_name(); + if let Some(idx) = self.scripts.iter().position(|s| s.get_name() == name) { + js_log("Replacing exisiting"); + let _ = std::mem::replace(&mut self.scripts[idx], script); + } else { + js_log("Inserting new"); + self.scripts.push(script); + } + } + + pub fn get_script_by_name(&self, script_name: String) -> Option<&Box> { + for script in self.scripts.iter() { + if script.get_name() == script_name { + return Some(script); + } + } + None + } + + pub fn get_script_by_name_mut( + &mut self, + script_name: String, + ) -> Option<&mut Box> { + for script in self.scripts.iter_mut() { + if script.get_name() == script_name { + return Some(script); + } + } + None + } + + pub fn get_scripts_mut(&mut self) -> &mut Vec> { + &mut self.scripts + } + + pub fn iter_mut(&mut self) -> std::slice::IterMut> { + self.scripts.iter_mut() + } + + pub fn ensure_script(&mut self, script_name: String) -> () { + js_log(&format!("Ensuring Script: {}", script_name)); + let existing = self.get_script_by_name(script_name.clone()); + if existing.is_some() { + return (); + } + let game_script = GameScripts::build_script_from_registry(script_name); + + self.schedule_script_for_mount(game_script); + } + + pub fn get_script_state(&self, script_name: String) -> JsValue { + let script = self + .get_script_by_name(script_name.clone()) + .expect(&format!("Can't find script {:?}", script_name)); + + script.get_state_wasm() + } + + pub fn set_script_state(&mut self, script_name: String, state: JsValue) { + let script = self + .get_script_by_name_mut(script_name.clone()) + .expect(&format!("Can't find script {:?}", script_name)); + + script.set_state_wasm(state); + } + + pub fn get_all_script_names(&self) -> Vec { + self.scripts + .iter() + .map(|script| script.get_name()) + .collect() + } + + pub fn get_script_config(&self, script_name: String) -> JsValue { + for script in self.scripts.iter() { + if script.get_name() == script_name { + return script.get_config(); + } + } + JsValue::null() + } + + pub fn set_script_config(&mut self, script_name: String, config: JsValue) { + for script in self.scripts.iter_mut() { + if script.get_name() == script_name { + script.set_config(config); + break; + } + } + } + + pub fn to_js(&self) -> Result { + serde_wasm_bindgen::to_value(self) + } +} + +#[wasm_bindgen] +impl GameScripts { + #[wasm_bindgen(js_name = "fromJs")] + pub fn from_js(value: JsValue) -> Result { + let entity_holder: GameScripts = serde_wasm_bindgen::from_value(value)?; + Ok(entity_holder) + } +} + +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "ensureScript")] + pub fn ensure_script(&mut self, script_name: String) { + self.scripts.ensure_script(script_name); + } + + #[wasm_bindgen(js_name = "getScriptsJs")] + pub fn get_scripts_js(&self) -> Result { + self.scripts.to_js() + } + + #[wasm_bindgen(js_name = "getScriptState")] + pub fn get_script_state(&self, script_name: String) -> JsValue { + self.scripts.get_script_state(script_name) + } + + #[wasm_bindgen(js_name = "setScriptState")] + pub fn set_script_state(&mut self, script_name: String, state: JsValue) { + self.scripts.set_script_state(script_name, state); + } + + #[wasm_bindgen(js_name = "getScriptConfig")] + pub fn get_script_config(&self, script_name: String) -> JsValue { + self.scripts.get_script_config(script_name) + } + + #[wasm_bindgen(js_name = "getScriptNames")] + pub fn get_all_script_names(&self) -> Vec { + self.scripts.get_all_script_names() + } + + #[wasm_bindgen(js_name = "setScriptConfig")] + pub fn set_script_config(&mut self, script_name: String, val: JsValue) { + self.scripts.set_script_config(script_name, val); + } +} + +#[wasm_bindgen] +#[derive(Debug)] +pub struct WasmGameScript { + name: String, + context: JsValue, + get_config_jsfn: js_sys::Function, + set_config_jsfn: js_sys::Function, + on_script_mounted_jsfn: js_sys::Function, + on_chunk_update_jsfn: js_sys::Function, + on_entity_update_jsfn: js_sys::Function, +} + +#[wasm_bindgen] +impl WasmGameScript { + pub fn get_name_from_class(js_class: &JsValue) -> String { + js_sys::Reflect::get(&js_class, &JsValue::from("name")) + .expect("Class should have a static name property") + .as_string() + .expect("Name should be a string") + } + + #[wasm_bindgen(constructor)] + pub fn make_from_class(js_class: &JsValue) -> WasmGameScript { + use js_sys::Reflect::{construct, get}; + use js_sys::{Array, Function}; + + let name = WasmGameScript::get_name_from_class(js_class); + + let factory: Function = js_class + .clone() + .dyn_into() + .expect("argument must be a class/constructor Function"); + + let args = Array::new(); + + let js_class_instance = construct(&factory, &args).expect("constructing script failed"); + + js_log(&format!( + "Making wasm game script from value {:?}", + js_class_instance + )); + + let on_script_mounted_jsfn = get(&js_class_instance, &JsValue::from("onScriptMounted")) + .expect("Can't find method onScriptMounted"); + let on_chunk_update_jsfn = get(&js_class_instance, &JsValue::from("onChunkUpdate")) + .expect("Can't find method onChunkUpdate"); + let on_entity_update_jsfn = get(&js_class_instance, &JsValue::from("onEntityUpdate")) + .expect("can't find onEntityUpdate"); + let get_config_jsfn = + get(&js_class_instance, &JsValue::from("getConfig")).expect("can't find getConfig"); + let set_config_jsfn = + get(&js_class_instance, &JsValue::from("setConfig")).expect("can't find setConfig"); + + WasmGameScript { + name, + on_script_mounted_jsfn: on_script_mounted_jsfn.into(), + on_chunk_update_jsfn: on_chunk_update_jsfn.into(), + on_entity_update_jsfn: on_entity_update_jsfn.into(), + get_config_jsfn: get_config_jsfn.into(), + set_config_jsfn: set_config_jsfn.into(), + context: js_class_instance, + } + } +} + +impl GameScript for WasmGameScript { + fn update( + &mut self, + _world: &World, + _query_results: EntityQueryResults, + _chunk_fetcher: &mut ChunkFetcher, + _delta_ms: f32, + ) -> Option { + None + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_config(&self) -> JsValue { + self.get_config_jsfn.call0(&self.context).unwrap() + } + + fn set_config(&mut self, config: JsValue) { + self.set_config_jsfn.call1(&self.context, &config).unwrap(); + } + + fn on_script_mounted( + &mut self, + world: &World, + entities: &Entities, + _chunk_fetcher: &mut ChunkFetcher, + ) { + // For JavaScript scripts, we pass the IDs since they can access + // the full Game object to get World/Entities data as needed + let all_chunk_ids = world.get_all_chunk_ids(); + let all_entity_ids = entities.get_all_entity_ids(); + let val = serde_wasm_bindgen::to_value(&all_chunk_ids).unwrap(); + let val2 = serde_wasm_bindgen::to_value(&all_entity_ids).unwrap(); + self.on_script_mounted_jsfn + .call2(&self.context, &val, &val2) + .unwrap(); + } + + fn on_chunk_update(&self, chunk_id: ChunkId) { + let val = serde_wasm_bindgen::to_value(&chunk_id).unwrap(); + self.on_chunk_update_jsfn + .call1(&self.context, &val) + .unwrap(); + } + + fn on_entity_update(&self, entity_id: EntityId) { + let val = serde_wasm_bindgen::to_value(&entity_id).unwrap(); + self.on_entity_update_jsfn + .call1(&self.context, &val) + .unwrap(); + } + + fn get_state_wasm(&self) -> JsValue { + self.context.clone() + } + + fn set_state_wasm(&mut self, val: JsValue) { + self.context = val; + } +} + +type ScriptDeserializer = fn() -> Box; + +lazy_static! { + pub static ref SCRIPT_REGISTRY: Mutex> = { + let mut map = HashMap::new(); + fn register( map: &mut HashMap, ) { + fn deser() -> Box { + Box::new(T::default()) + } + let key = T::default().get_name(); + map.insert(key, deser::); + } + // Register all the scripts! + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + register::(&mut map); + Mutex::new(map) + }; +} + +thread_local! { + static WASM_SCRIPT_REGISTERY: RefCell> = + RefCell::new(HashMap::new()); +} + +type WasmScriptDeserializer = Box Box>; + +#[wasm_bindgen] +pub fn add_script_to_registry(game_script_class: JsValue) { + js_log(&format!( + "Adding WASM script to registry{:?}", + game_script_class + )); + let name = WasmGameScript::get_name_from_class(&game_script_class); + + let des: WasmScriptDeserializer = Box::new(move || -> Box { + let js_game_script = WasmGameScript::make_from_class(&game_script_class); + Box::new(js_game_script) + }); + + WASM_SCRIPT_REGISTERY.with(|reg| { + reg.borrow_mut().insert(name.clone(), des); + }); +} diff --git a/lib/world/src/scripts/mod.rs b/lib/world/src/scripts/mod.rs new file mode 100644 index 0000000..6c11b5f --- /dev/null +++ b/lib/world/src/scripts/mod.rs @@ -0,0 +1,10 @@ +pub mod game_script; +pub mod player_belt_script; +pub mod player_gravity_script; +pub mod player_jump_script; +pub mod player_move_script; +pub mod player_rot_script; +pub mod sandbox; +pub mod script_map; +pub mod player_tp_script; +pub mod velocity_script; diff --git a/lib/world/src/scripts/player_belt_script.rs b/lib/world/src/scripts/player_belt_script.rs new file mode 100644 index 0000000..2c911d8 --- /dev/null +++ b/lib/world/src/scripts/player_belt_script.rs @@ -0,0 +1,254 @@ +use crate::{ + block::{BlockData, BlockType}, + components::{fine_world_pos::FineWorldPos, velocity::Velocity}, + geometry::{ray::Ray, rotation::SphericalRotation}, + utils::js_log, + world::world_block::WorldBlock, +}; + +use crate::entities::{entity_action::EntityActionHandler, fireball::make_fireball}; +use crate::game::GameSchedule; +use serde::{Deserialize, Serialize}; +use tsify::Tsify; + +use crate::entities::{ + entity::{Entity, EntityId}, + entity_action::{EntityActionDto, EntityActionDtoMaker}, + entity_component::impl_component, +}; +use crate::geometry::direction::DirectionVectorExtension; +use crate::{geometry::vec::Vector3Ops, world::World}; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; + +// ================== Primary Action ================== +#[wasm_bindgen] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct UsePrimaryItemActionData {} + +#[wasm_bindgen] +#[derive(Clone, Debug, Default)] +pub struct UsePrimaryItemAction {} + +#[wasm_bindgen] +impl UsePrimaryItemAction { + pub fn make_wasm(entity_id: EntityId) -> EntityActionDto { + let data = UsePrimaryItemActionData {}; + UsePrimaryItemAction::make_dto(entity_id, data) + } +} + +impl EntityActionDtoMaker for UsePrimaryItemAction { + fn get_action_type_static() -> &'static str { + "UseItemAction" + } +} + +impl EntityActionHandler for UsePrimaryItemAction { + fn get_action_type(&self) -> &'static str { + "UseItemAction" + } + + fn handle_dto( + &self, + world: &World, + entity: &mut Entity, + _data: &EntityActionDto, + ) -> GameSchedule { + let mut schedule = GameSchedule::empty(); + let belt = entity.get::().unwrap(); + let pos = entity.get::().unwrap(); + let rot = entity.get::().unwrap(); + let selected_item = belt.selected_item; + let belt_item = belt.belt_items[selected_item]; + + if let Item::Fireball = belt_item { + let eye_pos_offset = FineWorldPos::new(0.4, 1.5, 0.4); + let mut fireball_vel: Velocity = (*rot).into(); + fireball_vel = fireball_vel.set_mag(0.1); + + let pos_offset = pos + .add(&eye_pos_offset) + .add(&fireball_vel.scalar_mult(10.0)); + + let fireball = make_fireball(pos_offset, fireball_vel); + schedule.add_entity(fireball); + } else if let Item::Block(block_type) = belt_item { + let eye_pos_offset = FineWorldPos::new(0.4, 1.5, 0.4); + + let camera_ray = Ray { + pos: pos.add(&eye_pos_offset), + rot: *rot, + }; + + let pointed_at = world.get_pointed_at_block(camera_ray); + + js_log(&format!("pointed_at: {:?}", pointed_at)); + + if let Some(pointed_at) = pointed_at { + let looking_at_pos = pointed_at.block.world_pos; + js_log(&format!("looking_at_pos: {:?}", looking_at_pos)); + let new_pos = looking_at_pos.move_direction(&pointed_at.face); + let block = WorldBlock { + block_type, + extra_data: BlockData::None, + world_pos: new_pos, + }; + + schedule.add_block(block); + } + } + + schedule + } +} + +// ================== Secondary Action ================== +#[wasm_bindgen] +#[derive(Clone, Debug, Default)] +pub struct SecondaryBeltAction {} + +#[wasm_bindgen] +impl SecondaryBeltAction { + pub fn make_wasm(entity_id: EntityId) -> EntityActionDto { + let data = SecondaryBeltActionData {}; + SecondaryBeltAction::make_dto(entity_id, data) + } +} + +#[wasm_bindgen] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct SecondaryBeltActionData {} + +impl EntityActionDtoMaker for SecondaryBeltAction { + fn get_action_type_static() -> &'static str { + "SecondaryBeltAction" + } +} + +impl EntityActionHandler for SecondaryBeltAction { + fn get_action_type(&self) -> &'static str { + "SecondaryBeltAction" + } + + fn handle_dto( + &self, + world: &World, + entity: &mut Entity, + _data: &EntityActionDto, + ) -> GameSchedule { + let mut schedule = GameSchedule::empty(); + let pos = entity.get::().unwrap(); + let rot = entity.get::().unwrap(); + let eye_pos_offset = FineWorldPos::new(0.4, 1.5, 0.4); + + let camera_ray = Ray { + pos: pos.add(&eye_pos_offset), + rot: *rot, + }; + + let pointed_at = world.get_pointed_at_block(camera_ray); + + if let Some(pointed_at) = pointed_at { + let looking_at_pos = pointed_at.block.world_pos; + schedule.remove_block(looking_at_pos); + } + + schedule + } +} + +// ================== Select Item Action ================== + +#[wasm_bindgen] +#[derive(Clone, Debug, Default)] +pub struct SelectItemAction {} + +#[wasm_bindgen] +impl SelectItemAction { + pub fn make_wasm(entity_id: EntityId, item_index: usize) -> EntityActionDto { + let data = SelectItemActionData { item_index }; + SelectItemAction::make_dto(entity_id, data) + } +} + +#[wasm_bindgen] +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct SelectItemActionData { + pub item_index: usize, +} + +impl EntityActionDtoMaker for SelectItemAction { + fn get_action_type_static() -> &'static str { + "SelectItemAction" + } +} + +impl EntityActionHandler for SelectItemAction { + fn get_action_type(&self) -> &'static str { + "SelectItemAction" + } + + fn handle_dto( + &self, + _world: &World, + entity: &mut Entity, + data: &EntityActionDto, + ) -> GameSchedule { + let mut belt = entity.get::().unwrap().to_owned(); + let data = data.get_data::().unwrap(); + belt.selected_item = data.item_index; + entity.set::(belt); + GameSchedule::empty() + } +} + +// ================== Items ================== + +#[derive(Clone, Debug, Serialize, Deserialize, Tsify, Copy)] +pub enum Item { + Fireball, + Block(BlockType), +} + +// ================== Belt ================== + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[wasm_bindgen] +pub struct Belt { + belt_items: [Item; 10], + pub selected_item: usize, +} + +#[wasm_bindgen] +impl Belt { + pub fn get_item_js(&self, index: usize) -> JsValue { + serde_wasm_bindgen::to_value(&self.belt_items[index]).unwrap() + } + + pub fn get_num_items(&self) -> usize { + self.belt_items.len() + } +} + +impl Default for Belt { + fn default() -> Self { + let belt_items = [ + Item::Block(BlockType::Gold), + Item::Block(BlockType::Stone), + Item::Block(BlockType::Grass), + Item::Block(BlockType::Water), + Item::Block(BlockType::Planks), + Item::Block(BlockType::Red), + Item::Block(BlockType::RedFlower), + Item::Block(BlockType::Wood), + Item::Block(BlockType::Leaf), + Item::Fireball, + ]; + Belt { + belt_items, + selected_item: 0, + } + } +} + +impl_component!(Belt); diff --git a/lib/world/src/scripts/player_gravity_script.rs b/lib/world/src/scripts/player_gravity_script.rs new file mode 100644 index 0000000..961d960 --- /dev/null +++ b/lib/world/src/scripts/player_gravity_script.rs @@ -0,0 +1,93 @@ +use crate::entities::entities::{EntityQuery, EntityQueryResults}; +use crate::entities::entity_component::impl_component; +use crate::game::GameSchedule; +use crate::scripts::game_script::GameScript; +use crate::scripts::velocity_script::Forces; +use crate::{chunk::chunk_fetcher::ChunkFetcher, components::velocity::Velocity, world::World}; +use serde::{Deserialize, Serialize}; +use serde_json; +use serde_wasm_bindgen; +use wasm_bindgen::JsValue; + +#[derive(Debug, Serialize, Deserialize, Default, Clone)] +pub struct GravityData { + pub has_gravity: bool, +} + +impl_component!(GravityData); + +#[derive(Debug, Serialize, Deserialize)] +pub struct GravityScript { + gravity: f32, +} + +impl Default for GravityScript { + fn default() -> Self { + Self { gravity: 0.011 } + } +} + +impl GravityScript { + pub fn name() -> String { + "gravity".to_string() + } +} + +impl GameScript for GravityScript { + fn get_name(&self) -> String { + "gravity".to_string() + } + + fn get_config(&self) -> JsValue { + let config = serde_json::json!({ + "gravity_strength": self.gravity, + }); + serde_wasm_bindgen::to_value(&config).unwrap() + } + + fn set_config(&mut self, config: JsValue) { + if let Ok(config_obj) = serde_wasm_bindgen::from_value::(config.clone()) + { + if let Some(gravity) = config_obj.get("gravity_strength").and_then(|v| v.as_f64()) { + self.gravity = gravity as f32; + } + } + web_sys::console::log_1(&format!("GravityScript config updated: {:?}", config).into()); + } + + fn get_query(&self) -> EntityQuery { + let mut query = EntityQuery::new(); + query.add::(); + query.add::(); + query.add::(); + query + } + + fn update( + &mut self, + _world: &World, + query_results: EntityQueryResults, + _chunk_fetcher: &mut ChunkFetcher, + _delta_ms: f32, + ) -> Option { + for entity in query_results.entities { + let data = entity.get::().unwrap(); + + if !data.has_gravity { + continue; + } + + let gravity_force = Velocity { + x: 0.0, + y: -self.gravity, + z: 0.0, + }; + + let mut forces = entity.get::().unwrap().to_owned(); + forces.add_force(gravity_force); + entity.set::(forces); + } + + None + } +} diff --git a/lib/world/src/scripts/player_jump_script.rs b/lib/world/src/scripts/player_jump_script.rs new file mode 100644 index 0000000..f9db7d1 --- /dev/null +++ b/lib/world/src/scripts/player_jump_script.rs @@ -0,0 +1,99 @@ +use serde::{Deserialize, Serialize}; + +use crate::entities::entity::{Entity, EntityId}; +use crate::entities::entity_action::{EntityActionDto, EntityActionDtoMaker, EntityActionHandler}; +use crate::entities::entity_component::impl_component; +use crate::game::GameSchedule; +use crate::{ + components::velocity::Velocity, scripts::velocity_script::Forces, utils::js_log, world::World, +}; +use wasm_bindgen::prelude::wasm_bindgen; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct JumpActionData {} + +#[derive(Clone, Debug, Default)] +#[wasm_bindgen] +pub struct JumpAction {} +impl EntityActionDtoMaker for JumpAction { + fn get_action_type_static() -> &'static str { + "Jump-Action" + } +} + +impl EntityActionHandler for JumpAction { + fn get_action_type(&self) -> &'static str { + "Jump-Action" + } + + fn handle_dto( + &self, + _world: &World, + entity: &mut Entity, + _data: &EntityActionDto, + ) -> GameSchedule { + let jump_data = entity.get::().unwrap().to_owned(); + let mut forces = entity.get::().unwrap().to_owned(); + + let jump_force = Velocity { + x: 0.0, + y: jump_data.jump_speed, + z: 0.0, + }; + + forces.add_force(jump_force); + + js_log(&format!("jump_force: {:?}", jump_force)); + + entity.set::(forces); + + GameSchedule::empty() + } +} + +#[wasm_bindgen] +#[derive(Debug, Serialize, Deserialize, Clone, Copy)] +pub struct JumpData { + jump_speed: f32, + is_jumping: bool, + have_db_jumped: bool, + jump_count: u8, +} + +impl Default for JumpData { + fn default() -> Self { + Self::new(0.25) + } +} + +impl JumpData { + pub fn new(jump_speed: f32) -> Self { + Self { + jump_speed, + is_jumping: false, + have_db_jumped: false, + jump_count: 0, + } + } + + pub fn stop_jumping(&self) -> JumpData { + JumpData { + is_jumping: false, + ..*self + } + } +} + +impl_component!(JumpData); + +pub mod wasm { + use super::*; + + #[wasm_bindgen] + impl JumpAction { + pub fn make_wasm(entity_id: EntityId) -> EntityActionDto { + let data = JumpActionData {}; + JumpAction::make_dto(entity_id, data) + } + } +} diff --git a/lib/world/src/scripts/player_move_script.rs b/lib/world/src/scripts/player_move_script.rs new file mode 100644 index 0000000..52a5730 --- /dev/null +++ b/lib/world/src/scripts/player_move_script.rs @@ -0,0 +1,157 @@ +use crate::entities::entities::{EntityQuery, EntityQueryResults}; +use crate::entities::entity::Entity; +use crate::entities::entity_action::{EntityActionDto, EntityActionDtoMaker, EntityActionHandler}; +use crate::entities::entity_component::impl_component; +use crate::game::GameSchedule; +use crate::scripts::game_script::GameScript; +use crate::scripts::velocity_script::Forces; +use crate::{ + chunk::chunk_fetcher::ChunkFetcher, components::velocity::Velocity, + geometry::direction::Direction, geometry::rotation::SphericalRotation, + geometry::vec::Vector3Ops, world::World, +}; +use serde::{Deserialize, Serialize}; +use serde_json; +use serde_wasm_bindgen; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct MoveActionData { + pub direction: Option, +} + +#[derive(Clone, Debug, Default)] +#[wasm_bindgen] +pub struct MoveAction {} +impl EntityActionDtoMaker for MoveAction { + fn get_action_type_static() -> &'static str { + "Move" + } +} +impl EntityActionHandler for MoveAction { + fn get_action_type(&self) -> &'static str { + "Move" + } + + fn handle_dto( + &self, + _world: &World, + entity: &mut Entity, + data: &EntityActionDto, + ) -> GameSchedule { + let data = data.get_data::().unwrap(); + entity.set::(data.direction); + GameSchedule::empty() + } +} + +pub type MovingDirection = Option; +impl_component!(MovingDirection); + +#[derive(Debug, Serialize, Deserialize)] +pub struct MoveScript { + pub max_speed: f32, +} + +impl MoveScript { + pub fn name() -> String { + "move".to_string() + } +} + +impl Default for MoveScript { + fn default() -> Self { + Self { max_speed: 0.2 } + } +} + +impl GameScript for MoveScript { + fn get_name(&self) -> String { + "move".to_string() + } + + fn get_config(&self) -> JsValue { + serde_wasm_bindgen::to_value(&self).unwrap() + } + + fn set_config(&mut self, config: JsValue) { + if let Ok(config_obj) = serde_wasm_bindgen::from_value::(config.clone()) + { + if let Some(max_speed) = config_obj.get("max_speed").and_then(|v| v.as_f64()) { + self.max_speed = max_speed as f32; + } + } + web_sys::console::log_1(&format!("MoveScript config updated: {:?}", config).into()); + } + + fn get_query(&self) -> EntityQuery { + let mut query = EntityQuery::new(); + query.add::(); + query.add::(); + query.add::(); + query.add::(); + query + } + + fn update( + &mut self, + _world: &crate::world::World, + query_results: EntityQueryResults, + _chunk_fetcher: &mut ChunkFetcher, + _delta_ms: f32, + ) -> Option { + for entity in query_results.entities { + let rot = entity.get::().unwrap().to_owned(); + let moving_dir = entity.get::().unwrap().to_owned(); + let vel = entity.get::().unwrap().to_owned(); + let mut forces = entity.get::().unwrap().to_owned(); + + if moving_dir.is_some() { + let direction_rot: SphericalRotation = moving_dir.unwrap().into(); + let move_rot = rot + direction_rot; + let mut move_force: Velocity = move_rot.into(); + + // check if this move force would make the player exceed the max speed, if so, scale the force down so it would make us reach the max speed once applied + let final_vel = vel.add(&move_force); + let max_vel = move_force.set_mag(self.max_speed); + if final_vel.get_mag() > max_vel.get_mag() { + move_force = max_vel.sub(&vel); + } + + // don't allow the player to move up or down + move_force.y = 0.0; + + forces.add_force(move_force); + entity.set::(forces); + } else { + // If the player is moving, then slow them down by applying a force in the opposite direction of their velocity until they reach 0 velocity + let mut new_forces = forces.forces.clone(); + let vel_mag = vel.get_mag(); + if vel_mag > 0.0 { + let slow_force_mag = f32::min(vel_mag, 0.1); + let mut slow_force = vel.set_mag(-slow_force_mag); + slow_force.y = 0.0; + new_forces.push(slow_force); + } + entity.set::(Forces { forces: new_forces }); + } + } + + None + } +} + +pub mod wasm { + use crate::entities::entity::EntityId; + + use super::*; + + #[wasm_bindgen] + impl MoveAction { + pub fn make_wasm(entity_id: EntityId, direction: Option) -> EntityActionDto { + let data = MoveActionData { direction }; + MoveAction::make_dto(entity_id, data) + } + } +} diff --git a/lib/world/src/scripts/player_rot_script.rs b/lib/world/src/scripts/player_rot_script.rs new file mode 100644 index 0000000..43a0432 --- /dev/null +++ b/lib/world/src/scripts/player_rot_script.rs @@ -0,0 +1,60 @@ +use crate::entities::entity::{Entity, EntityId}; +use crate::entities::entity_action::{EntityActionDto, EntityActionDtoMaker, EntityActionHandler}; +use crate::game::GameSchedule; +use crate::geometry::rotation::SphericalRotation; +use crate::world::World; +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct RotateActionData { + pub rot: SphericalRotation, +} + +#[wasm_bindgen] +#[derive(Clone, Debug, Default)] +pub struct RotateAction {} + +impl EntityActionDtoMaker for RotateAction { + fn get_action_type_static() -> &'static str { + "Player-Rotate" + } +} +impl EntityActionHandler for RotateAction { + fn get_action_type(&self) -> &'static str { + "Player-Rotate" + } + + fn handle_dto( + &self, + _world: &World, + entity: &mut Entity, + data: &EntityActionDto, + ) -> GameSchedule { + let data = data.get_data::().unwrap(); + + entity.set::(data.rot); + + GameSchedule::empty() + } +} + +pub mod wasm { + use wasm_bindgen::JsValue; + + use super::*; + + #[wasm_bindgen] + impl RotateAction { + pub fn make_wasm(entity_id: EntityId, rot: SphericalRotation) -> EntityActionDto { + let data = RotateActionData { rot }; + RotateAction::make_dto(entity_id, data) + } + + pub fn serialize_wasm(action: EntityActionDto) -> JsValue { + let data = action.get_data::().unwrap(); + serde_wasm_bindgen::to_value(&data).unwrap() + } + } +} diff --git a/lib/world/src/scripts/player_tp_script.rs b/lib/world/src/scripts/player_tp_script.rs new file mode 100644 index 0000000..5acb508 --- /dev/null +++ b/lib/world/src/scripts/player_tp_script.rs @@ -0,0 +1,67 @@ +use serde::{Deserialize, Serialize}; + +use crate::components::fine_world_pos::FineWorldPos; +use crate::components::velocity::Velocity; +use crate::entities::entity::{Entity, EntityId}; +use crate::entities::entity_action::{EntityActionDto, EntityActionDtoMaker, EntityActionHandler}; +use crate::game::GameSchedule; +use crate::utils::js_log; +use crate::world::World; +use wasm_bindgen::prelude::wasm_bindgen; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct TeleportActionData { + pub x: f32, + pub y: f32, + pub z: f32, +} + +#[derive(Clone, Debug, Default)] +#[wasm_bindgen] +pub struct TeleportAction {} + +impl EntityActionDtoMaker for TeleportAction { + fn get_action_type_static() -> &'static str { + "Teleport" + } +} + +impl EntityActionHandler for TeleportAction { + fn get_action_type(&self) -> &'static str { + "Teleport" + } + + fn handle_dto( + &self, + _world: &World, + entity: &mut Entity, + data: &EntityActionDto, + ) -> GameSchedule { + let data = data.get_data::().unwrap(); + + let new_pos = FineWorldPos { + x: data.x, + y: data.y, + z: data.z, + }; + + js_log(&format!("Teleporting entity to {:?}", new_pos)); + + entity.set::(new_pos); + entity.set::(Velocity::default()); + + GameSchedule::empty() + } +} + +pub mod wasm { + use super::*; + + #[wasm_bindgen] + impl TeleportAction { + pub fn make_wasm(entity_id: EntityId, x: f32, y: f32, z: f32) -> EntityActionDto { + let data = TeleportActionData { x, y, z }; + TeleportAction::make_dto(entity_id, data) + } + } +} diff --git a/lib/world/src/scripts/sandbox.rs b/lib/world/src/scripts/sandbox.rs new file mode 100644 index 0000000..1498ba2 --- /dev/null +++ b/lib/world/src/scripts/sandbox.rs @@ -0,0 +1,160 @@ +use crate::chunk::chunk_pos::ChunkPos; +use crate::entities::entities::{Entities, EntityQuery, EntityQueryResults}; +use crate::game::GameSchedule; +use crate::scripts::game_script::GameScript; +use crate::{ + chunk::chunk_fetcher::ChunkFetcher, components::fine_world_pos::FineWorldPos, world::World, +}; +use serde::Serialize; +use serde_json; +use serde_wasm_bindgen; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; + +pub trait RequestChunk: std::fmt::Debug { + fn request_chunk(&self, chunk_pos: ChunkPos); +} + +static NAME: &'static str = "sandbox"; + +#[derive(Debug, Serialize)] +#[wasm_bindgen] +pub struct SandBoxGScript { + pub load_distance: u8, +} + +impl Default for SandBoxGScript { + fn default() -> Self { + Self { load_distance: 2 } + } +} + +#[wasm_bindgen] +impl SandBoxGScript { + #[wasm_bindgen(js_name = "name")] + pub fn get_name_wasm() -> String { + return NAME.to_string(); + } + + pub fn get_chunks_around_player(&self, pos: &FineWorldPos) -> Vec { + let mut poses = vec![]; + + let player_chunk_pos: ChunkPos = pos.to_world_pos().to_chunk_pos(); + + for i in -(self.load_distance as i16)..=self.load_distance as i16 { + for j in -(self.load_distance as i16)..=self.load_distance as i16 { + let chunk_pos = player_chunk_pos + ChunkPos { x: i, y: j }; + poses.push(chunk_pos); + } + } + + poses + } +} + +impl GameScript for SandBoxGScript { + fn get_name(&self) -> String { + NAME.to_string() + } + + fn get_config(&self) -> JsValue { + let config = serde_json::json!({ + "load_distance": self.load_distance, + }); + serde_wasm_bindgen::to_value(&config).unwrap() + } + + fn set_config(&mut self, config: JsValue) { + if let Ok(config_obj) = serde_wasm_bindgen::from_value::(config.clone()) + { + if let Some(load_distance) = config_obj.get("load_distance").and_then(|v| v.as_u64()) { + self.load_distance = load_distance as u8; + } + } + web_sys::console::log_1(&format!("SandBoxGScript config updated: {:?}", config).into()); + } + + fn get_query(&self) -> EntityQuery { + let mut query = EntityQuery::new(); + query.add::(); + query + } + + fn on_script_mounted( + &mut self, + world: &World, + entities: &Entities, + chunk_fetcher: &mut ChunkFetcher, + ) { + web_sys::console::log_1( + &format!( + "SandBoxGScript onScriptMounted: {} chunks, {} entities", + world.get_all_chunk_ids().len(), + entities.get_all_entity_ids().len() + ) + .into(), + ); + + // Request chunks around all entities on mount + let entity_poses: Vec = entities + .get_all() + .iter() + .filter_map(|ent| ent.get::().cloned()) + .collect(); + + let nearby_unloaded_chunks: Vec = entity_poses + .iter() + .flat_map(|p| self.get_chunks_around_player(p)) + .filter(|pos| !world.has_chunk(pos)) + .collect(); + + for chunk_pos in nearby_unloaded_chunks { + chunk_fetcher.request_chunk(chunk_pos); + } + } + + fn update( + &mut self, + world: &World, + query_results: EntityQueryResults, + chunk_fetcher: &mut ChunkFetcher, + _delta_ms: f32, + ) -> Option { + let entity_poses: Vec = query_results + .entities + .iter() + .map(|ent| ent.get::().unwrap().clone()) + .collect(); + + let nearby_unloaded_chunks: Vec = entity_poses + .iter() + .flat_map(|p| self.get_chunks_around_player(p)) + .filter(|pos| !world.has_chunk(pos)) + .collect(); + + for chunk_pos in nearby_unloaded_chunks { + chunk_fetcher.request_chunk(chunk_pos); + } + + None + } +} + +pub mod wasm { + use wasm_bindgen::JsValue; + + use super::*; + + #[wasm_bindgen] + impl SandBoxGScript { + #[wasm_bindgen(constructor)] + pub fn new_wasm() -> SandBoxGScript { + SandBoxGScript::default() + } + + pub fn serialize(&self) -> Result { + let serialized = serde_wasm_bindgen::to_value(self).unwrap(); + Ok(serialized) + } + } +} diff --git a/lib/world/src/scripts/script_map.rs b/lib/world/src/scripts/script_map.rs new file mode 100644 index 0000000..139597f --- /dev/null +++ b/lib/world/src/scripts/script_map.rs @@ -0,0 +1,2 @@ + + diff --git a/lib/world/src/scripts/velocity_script.rs b/lib/world/src/scripts/velocity_script.rs new file mode 100644 index 0000000..4ffc4b0 --- /dev/null +++ b/lib/world/src/scripts/velocity_script.rs @@ -0,0 +1,97 @@ +use crate::entities::entities::{EntityQuery, EntityQueryResults}; +use crate::entities::entity_component::impl_component; +use crate::game::GameSchedule; +use crate::scripts::game_script::GameScript; +use crate::{ + chunk::chunk_fetcher::ChunkFetcher, + components::{fine_world_pos::FineWorldPos, size3::Size3, velocity::Velocity}, + geometry::rect3::Rect3, + geometry::vec::Vector3Ops, +}; +use serde::{Deserialize, Serialize}; +use serde_json; +use serde_wasm_bindgen; +use wasm_bindgen::JsValue; + +#[derive(Debug, Default, Serialize, Deserialize, Clone)] +pub struct Forces { + pub forces: Vec, +} + +impl Forces { + pub fn add_force(&mut self, force: Velocity) { + self.forces.push(force); + } +} + +impl_component!(Forces); + +#[derive(Debug, Default)] +pub struct VelocityScript {} + +impl VelocityScript { + pub fn name() -> String { + "velocity".to_string() + } +} + +impl GameScript for VelocityScript { + fn get_name(&self) -> String { + "velocity".to_string() + } + + fn get_config(&self) -> JsValue { + let config = serde_json::json!({}); + serde_wasm_bindgen::to_value(&config).unwrap() + } + + fn set_config(&mut self, config: JsValue) { + web_sys::console::log_1(&format!("VelocityScript config updated: {:?}", config).into()); + } + + fn get_query(&self) -> EntityQuery { + let mut query = EntityQuery::new(); + query.add::(); + query.add::(); + query.add::(); + query + } + + fn update( + &mut self, + world: &crate::world::World, + query_results: EntityQueryResults, + _chunk_fetcher: &mut ChunkFetcher, + _delta_ms: f32, + ) -> Option { + for entity in query_results.entities { + let mut vel = entity.get::().unwrap().to_owned(); + let pos = entity.get::().unwrap().to_owned(); + let size = entity.get::().unwrap().to_owned(); + let forces = entity.get::().unwrap().to_owned(); + + for force in forces.forces.iter() { + vel = vel.add(force); + } + + let player_rect = Rect3 { pos, dim: size }; + + let end_pos = pos + vel; + + let new_pos = world.move_rect3(&player_rect, end_pos); + + let pos_diff = new_pos.sub(&pos); + let real_vel = Velocity { + x: pos_diff.x, + y: pos_diff.y, + z: pos_diff.z, + }; + + entity.set::(new_pos); + entity.set::(real_vel); + entity.set::(Forces { forces: vec![] }); + } + + None + } +} diff --git a/lib/world/src/terrain_gen.rs b/lib/world/src/terrain_gen.rs new file mode 100644 index 0000000..8fe652f --- /dev/null +++ b/lib/world/src/terrain_gen.rs @@ -0,0 +1,589 @@ +use crate::chunk::chunk_fetcher::ChunkLoader; +use crate::geometry::direction::DirectionVectorExtension2; +use crate::{ + block::{BlockData, BlockType, ChunkBlock}, + chunk::{chunk::Chunk, chunk::CHUNK_WIDTH}, + chunk::{chunk_pos::ChunkPos, inner_chunk_pos::InnerChunkPos}, + components::world_pos::WorldPos, + geometry::direction::{Direction, DirectionVectorExtension, Directions, EVERY_FLAT_DIRECTION}, + geometry::vec::Vector3Ops, + geometry::vec2::Vec2Ops, + world::world_block::WorldBlock, +}; +use noise::{NoiseFn, Perlin}; +use rand::{rngs::StdRng, SeedableRng}; +use rand_distr::{Distribution, Uniform}; +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; + +// remove all the positions that are too close to each other in the chunk +fn remove_close_positions<'a, I, J>(pos_iter: I, checking_pos_iter: J) -> Vec +where + I: IntoIterator, + J: IntoIterator + Clone, +{ + let mut out_positions = Vec::new(); + + for pos in pos_iter { + let mut too_close = false; + for other_pos in checking_pos_iter.clone() { + if pos.distance_to(other_pos) < 3.0 { + too_close = true; + break; + } + } + if !too_close { + out_positions.push(pos.to_owned()); + } + } + + out_positions +} + +struct TreeLocator { + world_x: i32, + world_z: i32, +} + +impl TreeLocator { + fn is_in_chunk(&self, chunk_pos: &ChunkPos) -> bool { + let my_chunk_pos = WorldPos { + x: self.world_x, + y: 0, + z: self.world_z, + } + .to_chunk_pos(); + + if my_chunk_pos == *chunk_pos { + return true; + } + + // check leaf blocks + for x in Directions::flat() { + let other_pos = WorldPos { + x: self.world_x, + y: 0, + z: self.world_z, + } + .move_direction(&x) + .to_chunk_pos(); + if other_pos == *chunk_pos { + return true; + } + } + + return false; + } + + fn get_world_blocks(&self, y_pos: i32) -> Vec { + let height = 5; + + // make trunk + let mut blocks = (0..height) + .map(|y| WorldBlock { + world_pos: WorldPos { + x: self.world_x, + y: y + y_pos, + z: self.world_z, + }, + block_type: BlockType::Wood, + extra_data: BlockData::None, + }) + .collect::>(); + + // add leaves at top + let mut leaf_dirs = Directions::all(); + leaf_dirs.remove_direction(Direction::Down); + for x in leaf_dirs { + let pos = WorldPos { + x: self.world_x, + y: height + y_pos, + z: self.world_z, + } + .move_direction(&x); + + blocks.push(WorldBlock { + world_pos: pos, + block_type: BlockType::Leaf, + extra_data: BlockData::None, + }); + } + + blocks + } +} + +pub struct TreeRandomSpreadGenerator { + seed: u64, + dist: Uniform, +} + +impl TreeRandomSpreadGenerator { + pub fn make_from_seed(seed: u64) -> TreeRandomSpreadGenerator { + TreeRandomSpreadGenerator { + seed, + dist: Uniform::new(0, CHUNK_WIDTH as u16), + } + } + + fn get_potential_tree_locations( + &self, + chunk_pos: ChunkPos, + ) -> Box> { + let chunk_seed = self.seed + chunk_pos.to_id(); + let mut rng: StdRng = SeedableRng::seed_from_u64(chunk_seed); + + let mut tree_locations: Vec = Vec::new(); + + // sample 40 numbers + let tree_locations_rnd = self + .dist + .sample_iter(&mut rng) + .take(40) + .collect::>(); + + for i in 0..20 { + let x = tree_locations_rnd[i]; + let z = tree_locations_rnd[i + 20]; + + let pos = WorldPos { + x: (chunk_pos.x * CHUNK_WIDTH) as i32 + x as i32, + y: 0, + z: (chunk_pos.y * CHUNK_WIDTH) as i32 + z as i32, + }; + + // loop over and make sure that the tree is not too close to any other trees + let mut too_close = false; + for other_pos in tree_locations.iter() { + if pos.distance_to(other_pos) < 3.0 { + too_close = true; + break; + } + } + + if too_close { + continue; + } + + tree_locations.push(pos); + } + + Box::new(tree_locations.into_iter()) + } + + fn get_tree_locations(self: &Self, chunk_pos: ChunkPos) -> Vec { + let corner_potential_tree_locations = self + .get_potential_tree_locations(ChunkPos { + x: chunk_pos.x + 1, + y: chunk_pos.y + 1, + }) + .collect::>(); + + let above_potential_tree_locations = self.get_potential_tree_locations(ChunkPos { + x: chunk_pos.x, + y: chunk_pos.y + 1, + }); + let right_potential_tree_locations = self.get_potential_tree_locations(ChunkPos { + x: chunk_pos.x + 1, + y: chunk_pos.y, + }); + + let nearby_potential_tree_locations = above_potential_tree_locations + .chain(right_potential_tree_locations) + .collect::>(); + + let nearby_valid_tree_locations = remove_close_positions( + nearby_potential_tree_locations.iter(), + corner_potential_tree_locations.iter(), + ); + + let potential_tree_locations = self + .get_potential_tree_locations(chunk_pos) + .collect::>(); + + let t = remove_close_positions( + potential_tree_locations.iter(), + nearby_valid_tree_locations.iter(), + ); + + t + } + + fn get_trees(self: &Self, chunk_pos: ChunkPos) -> Vec { + let tree_locations = self.get_tree_locations(chunk_pos); + + let mut trees = Vec::new(); + + for tree_location in tree_locations { + trees.push(TreeLocator { + world_x: tree_location.x, + world_z: tree_location.z, + }); + } + + // loop over nearby chunks to make sure there isn't an overlaping tree + for x in EVERY_FLAT_DIRECTION { + let other_chunk_pos = chunk_pos.move_in_flat_direction(&x); + let other_tree_locations = self.get_tree_locations(other_chunk_pos); + + let other_trees = other_tree_locations + .into_iter() + .map(|tree_location| TreeLocator { + world_x: tree_location.x, + world_z: tree_location.z, + }) + .filter(|tree_location| tree_location.is_in_chunk(&other_chunk_pos)) + .collect::>(); + + trees.extend(other_trees); + } + + trees + } +} + +struct FlowerGetter { + seed: u64, +} + +#[derive(Eq, PartialEq)] +struct FlowerLocator { + world_x: i32, + world_z: i32, +} + +impl FlowerLocator { + fn make_chunk_block(self: &Self, y_pos: i32) -> ChunkBlock { + ChunkBlock { + pos: WorldPos::new( + self.world_x % CHUNK_WIDTH as i32, + y_pos, + self.world_z % CHUNK_WIDTH as i32, + ) + .to_inner_chunk_pos(), + block_type: BlockType::RedFlower, + extra_data: BlockData::None, + } + } +} + +impl FlowerGetter { + fn get_flowers(self: &Self, chunk_pos: &ChunkPos) -> Vec { + // generate 15-25 random flowers per chunk + let chunk_seed = self.seed + chunk_pos.to_id(); + let mut rng: StdRng = SeedableRng::seed_from_u64(chunk_seed); + let dist = Uniform::new(0, CHUNK_WIDTH); + let flower_count_getter = Uniform::new(15, 25); + + let flower_count = flower_count_getter.sample(&mut rng); + + let mut flowers = Vec::new(); + + for _ in 0..flower_count { + let x = dist.sample(&mut rng); + let z = dist.sample(&mut rng); + + let loc = FlowerLocator { + world_x: (chunk_pos.x * CHUNK_WIDTH) as i32 + x as i32, + world_z: (chunk_pos.y * CHUNK_WIDTH) as i32 + z as i32, + }; + + let already_has_flower = flowers.iter().any(|other_loc| *other_loc == loc); + + if already_has_flower { + continue; + } + + flowers.push(loc); + } + + flowers + } +} + +struct BasicChunkGetter { + seed: u32, + jag_factor: f64, + height_multiplier: f64, +} + +impl BasicChunkGetter { + pub fn make(seed: u32) -> BasicChunkGetter { + BasicChunkGetter { + seed, + jag_factor: 1.0 / 100.0, + height_multiplier: 10.0, + } + } + + pub fn get_chunk(&self, chunk_pos: &ChunkPos) -> Chunk { + let noise = Perlin::new(self.seed); + + let get_height = |x: f64, z: f64| -> f64 { + let per_val = noise.get([x * self.jag_factor, z * self.jag_factor]); + let height = ((per_val.abs() * self.height_multiplier) + 5.0) as i32; + height as f64 + }; + + let mut chunk = Chunk::new(*chunk_pos); + + let trees_in_chunk = TreeRandomSpreadGenerator::make_from_seed(100); + + let trees = trees_in_chunk.get_trees(*chunk_pos); + + for tree in trees { + let height = get_height(tree.world_x as f64, tree.world_z as f64) as i32; + let blocks = tree.get_world_blocks(height); + for block in blocks { + let block_chunnk_pos = block.world_pos.to_chunk_pos(); + if block_chunnk_pos != *chunk_pos { + continue; + } + chunk.add_block(block.to_chunk_block()); + } + } + + // place flowers + let flowers_in_chunk = FlowerGetter { seed: 100 }; + + let flowers = flowers_in_chunk.get_flowers(&chunk_pos); + + for flower in flowers { + let height = get_height(flower.world_x as f64, flower.world_z as f64) as i32; + + let flower = flower.make_chunk_block(height + 1); + + // only place block if there isn't already a block there + if chunk.has_block(&flower.pos) { + continue; + } + + chunk.add_block(flower); + } + + for x in 0u8..CHUNK_WIDTH as u8 { + for z in 0u8..CHUNK_WIDTH as u8 { + let world_x = (chunk_pos.x * CHUNK_WIDTH as i16) as f64 + (x as f64); + let world_z = (chunk_pos.y * CHUNK_WIDTH as i16) as f64 + (z as f64); + + let per_val = noise.get([world_x * self.jag_factor, world_z * self.jag_factor]); + let height = ((per_val.abs() * self.height_multiplier) + 5.0) as u8; + + // use web_sys::console; + // console::log_1(&format!("height: {}", height).into()); + + for y in 0u8..height { + let block = ChunkBlock { + pos: InnerChunkPos::new(x as i8, y as i8, z as i8), + block_type: BlockType::Stone, + extra_data: BlockData::None, + }; + + chunk.add_block(block); + } + // add top grass block + let block = ChunkBlock { + pos: InnerChunkPos::new(x as i8, height as i8, z as i8), + block_type: BlockType::Grass, + extra_data: BlockData::None, + }; + chunk.add_block(block); + } + } + + chunk + } +} + +struct FlatWorldChunkGetter { + height: i32, +} + +impl FlatWorldChunkGetter { + pub fn get_chunk(&self, chunk_pos: &ChunkPos) -> Chunk { + let mut chunk = Chunk::new(*chunk_pos); + for x in 0u8..CHUNK_WIDTH as u8 { + for z in 0u8..CHUNK_WIDTH as u8 { + for y in 0..self.height { + let block = ChunkBlock { + pos: InnerChunkPos::new(x as i8, y as i8, z as i8), + block_type: BlockType::Grass, + extra_data: BlockData::None, + }; + chunk.add_block(block); + chunk.add_block(block); + } + } + } + chunk + } +} + +struct DebugWorldChunkGetter {} + +impl DebugWorldChunkGetter { + pub fn get_chunk(&self, chunk_pos: &ChunkPos) -> Chunk { + let mut chunk = Chunk::new(*chunk_pos); + let block = ChunkBlock { + pos: InnerChunkPos::new(0, 0, 0), + block_type: BlockType::Grass, + extra_data: BlockData::None, + }; + chunk.add_block(block); + chunk + } +} + +#[derive(Serialize, Deserialize)] +// #[wasm_bindgen] +struct ParkorChunkGetter { + // #[wasm_bindgen(skip)] + pub current_blocks: Vec, + + // how far away the blocks are generated from requested chunks + pub load_distance: u8, +} + +// #[wasm_bindgen] +impl ParkorChunkGetter { + pub fn new() -> ParkorChunkGetter { + ParkorChunkGetter { + current_blocks: Vec::new(), + load_distance: 4, + } + } + + pub fn get_chunk_wasm(&mut self, chunk_x: i16, chunk_y: i16) -> Chunk { + let chunk_pos = ChunkPos { + x: chunk_x, + y: chunk_y, + }; + self.get_chunk(&chunk_pos) + } +} + +impl ParkorChunkGetter { + pub fn get_next_block(&self) -> WorldBlock { + let current_block = self.current_blocks.last(); + + if let Some(block) = current_block { + let block_pos = block.world_pos; + + // compute the next pos + let next_pos = block_pos + .move_direction(&Direction::North) + .move_direction(&Direction::North); + + WorldBlock { + world_pos: next_pos, + block_type: BlockType::Stone, + extra_data: BlockData::None, + } + } else { + // return the first block + WorldBlock { + world_pos: WorldPos::new(0, 0, 0), + block_type: BlockType::Stone, + extra_data: BlockData::None, + } + } + } + + fn load_chunk(&mut self, chunk_pos: &ChunkPos) { + // check if there are any blocks in this chunk + let next_block = self.get_next_block(); + + let mut count = 0; + + // keep loading the next block until it isn't load distance away from me + while next_block.world_pos.to_chunk_pos().distance_to(chunk_pos) as u8 <= self.load_distance + && count < 10 + { + self.current_blocks.push(next_block); + let next_block = self.get_next_block(); + self.current_blocks.push(next_block); + count += 1; + } + } + + pub fn get_chunk(&mut self, chunk_pos: &ChunkPos) -> Chunk { + let mut chunk = Chunk::new(*chunk_pos); + + self.load_chunk(chunk_pos); + + for block in self.current_blocks.iter() { + let block_chunk_pos = block.world_pos.to_chunk_pos(); + if block_chunk_pos == *chunk_pos { + chunk.add_block(block.to_chunk_block()); + } + } + + chunk + } +} + +#[wasm_bindgen] +#[derive(Clone, Debug, Serialize, Deserialize, Copy)] +pub struct TerrainGenerator { + pub seed: u32, + pub flat_world: bool, + pub flat_world_height: i32, + pub debug_world: bool, +} + +impl Default for TerrainGenerator { + fn default() -> Self { + Self { + seed: 0, + flat_world: false, + flat_world_height: 5, + debug_world: false, + } + } +} + +#[wasm_bindgen] +impl TerrainGenerator { + #[wasm_bindgen(constructor)] + pub fn new( + seed: u32, + flat_world: bool, + flat_world_height: i32, + debug_world: bool, + ) -> TerrainGenerator { + TerrainGenerator { + seed, + flat_world, + flat_world_height, + debug_world, + } + } + + pub fn serialize(&self) -> Result { + let serialized = serde_wasm_bindgen::to_value(self).unwrap(); + Ok(serialized) + } + + pub fn get_chunk(&self, chunk_x: i16, chunk_y: i16) -> Chunk { + let chunk_pos = ChunkPos { + x: chunk_x, + y: chunk_y, + }; + + if self.flat_world { + let chunk_getter = FlatWorldChunkGetter { + height: self.flat_world_height, + }; + return chunk_getter.get_chunk(&chunk_pos); + } + + if self.debug_world { + let chunk_getter = DebugWorldChunkGetter {}; + return chunk_getter.get_chunk(&chunk_pos); + } + + let chunk_getter = BasicChunkGetter::make(self.seed); + chunk_getter.get_chunk(&chunk_pos) + } +} diff --git a/lib/world/src/utils.rs b/lib/world/src/utils.rs index de1f157..e4d242b 100644 --- a/lib/world/src/utils.rs +++ b/lib/world/src/utils.rs @@ -1,16 +1,6 @@ -#[allow(dead_code)] -pub fn set_panic_hook() { - // When the `console_error_panic_hook` feature is enabled, we can call the - // `set_panic_hook` function at least once during initialization, and then - // we will get better error messages if our code ever panics. - // - // For more details see - // https://github.com/rustwasm/console_error_panic_hook#readme - #[cfg(feature = "console_error_panic_hook")] - console_error_panic_hook::set_once(); +pub fn js_log(s: &str) { + if cfg!(target_arch = "wasm32") { + use wasm_bindgen::JsValue; + web_sys::console::log_1(&JsValue::from_str(s)); + } } - -// pub fn js_log(s: &str) { -// use wasm_bindgen::JsValue; -// web_sys::console::log_1(&JsValue::from_str(s)); -// } diff --git a/lib/world/src/vec.rs b/lib/world/src/vec.rs deleted file mode 100644 index 98ea8b4..0000000 --- a/lib/world/src/vec.rs +++ /dev/null @@ -1,368 +0,0 @@ -use crate::direction::{Axis, Direction, Directions, FlatDirection, EVERY_FLAT_DIRECTION}; -use num::{traits::real::Real, Num, One, Zero}; -use serde::{Deserialize, Serialize}; -use std::{ - fmt::Display, - ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign}, -}; - -#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)] -pub struct Vec2 { - pub x: T, - pub y: T, -} - -impl Vec2 { - pub fn new(x: T, y: T) -> Vec2 { - Vec2 { x, y } - } - - pub fn to_index(&self) -> String - where - T: Display, - { - format!("{},{}", self.x, self.y).as_str().to_owned() - } - - pub fn scalar_mul(&self, val: T) -> Vec2 - where - T: Mul + Copy, - { - Vec2 { - x: self.x * val, - y: self.y * val, - } - } - - pub fn add_vec(&self, vec: Vec2) -> Vec2 - where - T: Mul + Copy, - { - Vec2 { - x: self.x * vec.x, - y: self.y * vec.y, - } - } - - /** Returns a list of adjacent vectors that lie in a flat plane - * I.e no vectors that have a different y direction. - */ - pub fn get_adjacent_vecs(&self) -> Vec> - where - T: Copy + Add + AddAssign + One + SubAssign, - { - let mut adj_vecs: Vec> = Vec::new(); - for direction in EVERY_FLAT_DIRECTION { - let adj_vec = self.move_in_flat_direction(&direction); - adj_vecs.push(adj_vec); - } - adj_vecs - } - - // disclaimer, this is weird. - pub fn move_to_3d(&self, y_val: T) -> Vec3 - where - T: Copy, - { - Vec3 { - x: self.x, - y: y_val, - z: self.y, - } - } - - pub fn move_in_flat_direction(&self, direction: &FlatDirection) -> Vec2 - where - T: Copy + Add + AddAssign + One + SubAssign, - { - let mut new_vec = *self; - match direction { - FlatDirection::North => new_vec.y += T::one(), - FlatDirection::South => new_vec.y -= T::one(), - FlatDirection::East => new_vec.x += T::one(), - FlatDirection::West => new_vec.x -= T::one(), - } - new_vec - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct Vec3 { - pub x: T, - pub y: T, - pub z: T, -} - -impl Add> for Vec3 -where - T: Add + Copy, -{ - type Output = Vec3; - fn add(self, rhs: Vec3) -> Self::Output { - Vec3 { - x: self.x + rhs.x, - y: self.y + rhs.y, - z: self.z + rhs.z, - } - } -} - -impl Sub> for Vec3 -where - T: Sub + Copy, -{ - type Output = Vec3; - - fn sub(self, rhs: Vec3) -> Self::Output { - Vec3 { - x: self.x - rhs.x, - y: self.y - rhs.y, - z: self.z - rhs.z, - } - } -} - -impl Mul> for Vec3 -where - T: Mul + Copy, - U: Copy, -{ - type Output = Vec3; - - fn mul(self, rhs: Vec3) -> Self::Output { - Vec3 { - x: self.x * rhs.x, - y: self.y * rhs.y, - z: self.z * rhs.z, - } - } -} - -impl Mul for Vec3 -where - T: Mul + Copy, - U: Copy + Num, -{ - type Output = Vec3; - - fn mul(self, val: U) -> Self::Output { - Vec3 { - x: self.x * val, - y: self.y * val, - z: self.z * val, - } - } -} - -impl< - T: Add - + Sub - + Mul - + Display - + Copy - + AddAssign - + One - + SubAssign, - > Vec3 -{ - pub fn new(x: T, y: T, z: T) -> Vec3 { - Vec3 { x, y, z } - } - - pub fn get_mag(&self) -> f32 - where - T: Into, - { - let x_f32: f32 = self.x.into(); - let y_f32: f32 = self.y.into(); - let z_f32: f32 = self.z.into(); - (x_f32 * x_f32 + y_f32 * y_f32 + z_f32 * z_f32).sqrt() - } - - pub fn get_component_from_direction(&self, direction: Direction) -> T { - match direction { - Direction::North => self.z, - Direction::South => self.z, - Direction::East => self.x, - Direction::West => self.x, - Direction::Up => self.y, - Direction::Down => self.y, - } - } - - pub fn get_opposite_components_from_direction(&self, direction: Direction) -> (T, T) { - match direction { - Direction::North => (self.x, self.y), - Direction::South => (self.x, self.y), - Direction::East => (self.y, self.z), - Direction::West => (self.y, self.z), - Direction::Up => (self.x, self.z), - Direction::Down => (self.x, self.z), - } - } - - pub fn get_component_from_axis(&self, axis: Axis) -> T { - match axis { - Axis::X => self.x, - Axis::Y => self.y, - Axis::Z => self.z, - } - } - - pub fn set_component_from_axis(&mut self, axis: Axis, val: T) { - match axis { - Axis::X => self.x = val, - Axis::Y => self.y = val, - Axis::Z => self.z = val, - } - } - - pub fn to_index(&self) -> String { - format!("{},{},{}", self.x, self.y, self.z) - .as_str() - .to_owned() - } - - pub fn move_direction(&self, direction: &Direction) -> Vec3 { - let mut new_vec = self.clone(); - match direction { - Direction::North => new_vec.z += One::one(), - Direction::South => new_vec.z -= One::one(), - Direction::East => new_vec.x += One::one(), - Direction::West => new_vec.x -= One::one(), - Direction::Up => new_vec.y += One::one(), - Direction::Down => new_vec.y -= One::one(), - } - new_vec - } - - pub fn sum(&self) -> T { - self.x + self.y + self.z - } - - pub fn set_mag(&self, mag: T) -> Vec3 - where - T: Into + From + Div, - { - let current_mag = self.get_mag(); - let scale: T = mag / current_mag; - self.scalar_mult(scale) - } - - pub fn scalar_mult(&self, val: T) -> Vec3 { - Vec3 { - x: self.x * val, - y: self.y * val, - z: self.z * val, - } - } - - pub fn add_vec(&self, vec: Vec3) -> Vec3 - where - U: Add, - T: Add + Copy, - { - Vec3 { - x: self.x + vec.x, - y: self.y + vec.y, - z: self.z + vec.z, - } - } - - pub fn distance_to(&self, vec: Vec3) -> f32 - where - U: Sub + Copy + Mul + Add, - T: Sub + Copy + Mul + Add, - f32: From, - { - let diff = *self - vec; - let diff_squared = diff * diff; - let sum = diff_squared.sum(); - // take the sqrt of sum - let sum_f32: f32 = sum.into(); - sum_f32.sqrt() - } - - pub fn distance_to_2(&self, vec: &Vec3) -> V - where - U: Sub + Copy + Mul + Add, - T: Sub + Copy + Mul + Add, - V: From + Real, - { - let diff = *self - *vec; - let diff_squared = diff * diff; - let sum = diff_squared.sum(); - let sum_f32: V = sum.into(); - sum_f32.sqrt() - } - - pub fn map(&self, f: F) -> Vec3 - where - F: Fn(T) -> B, - { - Vec3 { - x: f(self.x), - y: f(self.y), - z: f(self.z), - } - } - - pub fn get_adjacent_vecs(&self) -> Vec> { - let mut vecs = Vec::new(); - for direction in Directions::all() { - vecs.push(self.move_direction(&direction)); - } - vecs - } - - /** - * Like get_adjacent_vecs, but also returns the original vector - */ - pub fn get_cross_vecs(&self) -> Vec> { - let mut vecs = Vec::new(); - vecs.push(self.clone()); - for direction in Directions::all() { - vecs.push(self.move_direction(&direction)); - } - vecs - } - - /** - * Returns all blocks in a cube around the vector - * I am not proud of this - */ - pub fn get_cube_vecs(&self) -> Vec> - where - T: Add + Sub + Copy + One + Neg + Zero, - { - let mut vecs = Vec::new(); - - vecs.push(self.clone()); - - for x in [-T::one(), T::one(), T::zero()].iter().cloned() { - for y in [-T::one(), T::one(), T::zero()].iter().cloned() { - for z in [-T::one(), T::one(), T::zero()].iter().cloned() { - vecs.push(Vec3::new(self.x + x, self.y + y, self.z + z)); - } - } - } - - vecs - } -} - -#[cfg(test)] -pub mod tests { - use crate::vec::Vec3; - - #[test] - fn test_distance_to() { - let vec1 = Vec3::new(0 as i16, 0 as i16, 0 as i16); - let vec2 = Vec3::new(1, 1, 1); - assert_eq!(vec1.distance_to(vec2), 1.7320508); - - let vec1 = Vec3::new(0 as i16, 0 as i16, 0 as i16); - let vec2 = Vec3::new(1, 0, 0); - assert_eq!(vec1.distance_to(vec2), 1.0); - } -} diff --git a/lib/world/src/world/mod.rs b/lib/world/src/world/mod.rs index 78ba5db..23136e6 100644 --- a/lib/world/src/world/mod.rs +++ b/lib/world/src/world/mod.rs @@ -1,13 +1,16 @@ use self::world_block::WorldBlock; +use crate::block::BlockType; +use crate::chunk::chunk::Chunk; use crate::chunk::chunk_mesh::ChunkMesh; -use crate::chunk::Chunk; -use crate::direction::{Direction, Directions}; -use crate::positions::{ChunkPos, WorldPos}; +use crate::components::world_pos::WorldPos; +use crate::game::Game; +use crate::geometry::direction::{Direction, DirectionVectorExtension, Directions}; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::{self, fmt}; +use tsify::Tsify; use wasm_bindgen::prelude::*; - pub mod world_block; mod world_chunk; mod world_duct; @@ -22,6 +25,7 @@ pub struct WorldPosWasm { } #[derive(Debug, Serialize, Deserialize)] +#[wasm_bindgen] pub struct ChunkNotLoadedError; impl std::error::Error for ChunkNotLoadedError {} @@ -43,18 +47,34 @@ impl fmt::Display for ChunkIndexOutOfBoundsError { } } +pub struct AdjacentBlocks { + pub data: [WorldBlock; 6], +} + +impl AdjacentBlocks { + pub fn new() -> Self { + Self { + data: [WorldBlock::empty(WorldPos { x: 0, y: 0, z: 0 }); 6], + } + } + + pub fn get_for_direction(&self, direction: Direction) -> &WorldBlock { + &self.data[direction.to_index()] + } +} + #[derive(Serialize, Deserialize)] pub struct WorldStateDiff { /** A list of chunk ids that were changed */ - pub chunk_ids: HashSet, + pub chunk_ids: HashSet, } -#[derive(Default, Serialize, Deserialize)] +#[derive(Default, Tsify, Serialize, Deserialize, Clone)] #[wasm_bindgen] pub struct World { - chunks: HashMap, - #[serde(skip)] - chunk_meshes: HashMap, + chunks: FxHashMap, + // #[serde(skip)] + chunk_meshes: FxHashMap, } impl World { @@ -76,7 +96,6 @@ impl World { } /** Returns void block when the chunk isn't loaded */ - /** ERROR, this isn't consistent. Idk if this is still relevant */ pub fn get_block(&self, world_pos: &WorldPos) -> WorldBlock { let chunk = self.get_chunk(&world_pos.to_chunk_pos()); @@ -89,15 +108,15 @@ impl World { * Always return all directions. * The directions that point to no block will just default to void * */ - fn get_adjacent_blocks(&self, world_pos: &WorldPos) -> HashMap { - let mut adjacent_blocks = HashMap::new(); + fn get_adjacent_blocks(&self, world_pos: &WorldPos) -> AdjacentBlocks { + let mut adjacent_blocks = AdjacentBlocks::new(); for direction in Directions::all() { let adjacent_pos = world_pos.move_direction(&direction); if !adjacent_pos.is_valid() { continue; } let block = self.get_block(&adjacent_pos); - adjacent_blocks.insert(direction, block); + adjacent_blocks.data[direction.to_index()] = block; } adjacent_blocks } @@ -121,11 +140,27 @@ impl World { } } +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "getBlock")] + pub fn get_block_js(&self, world_pos: &WorldPos) -> WorldBlock { + self.world.get_block(world_pos) + } + + #[wasm_bindgen(js_name = "getBlockType")] + pub fn get_block_type_js(&self, world_pos: &WorldPos) -> BlockType { + self.world.get_block(world_pos).block_type + } +} + #[cfg(test)] mod tests { use super::*; - use crate::block::{BlockData, BlockType}; - use crate::positions::WorldPos; + use crate::{ + block::{BlockData, BlockType}, + chunk::{chunk::Chunk, chunk_pos::ChunkPos}, + geometry::vec::Vector3Ops, + }; #[test] fn get_adjacent_blocks() { @@ -143,6 +178,6 @@ mod tests { let adjacent_blocks = world.get_adjacent_blocks(&world_pos); // Five because there is no block below me - assert_eq!(adjacent_blocks.len(), 5); + assert_eq!(adjacent_blocks.data.len(), 6); } } diff --git a/lib/world/src/world/world_block.rs b/lib/world/src/world/world_block.rs index 65fbd80..42787bc 100644 --- a/lib/world/src/world/world_block.rs +++ b/lib/world/src/world/world_block.rs @@ -1,14 +1,17 @@ use crate::{ block::{BlockData, BlockMetaData, BlockShape, BlockType, ChunkBlock}, - direction::{Direction, Directions}, - positions::WorldPos, + components::world_pos::WorldPos, + geometry::direction::Directions, + world::AdjacentBlocks, }; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; +use wasm_bindgen::prelude::*; #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)] +#[wasm_bindgen] pub struct WorldBlock { pub block_type: BlockType, + #[wasm_bindgen(skip)] pub extra_data: BlockData, pub world_pos: WorldPos, } @@ -56,16 +59,15 @@ impl WorldBlock { return false; } - pub fn get_visible_faces(&self, adjacent_blocks: HashMap) -> Directions { + pub fn get_visible_faces(&self, adjacent_blocks: &AdjacentBlocks) -> Directions { if self.block_type == BlockType::Void { return Directions::empty(); } self.get_faces() .into_iter() - .filter(|direction| match adjacent_blocks.get(direction) { - Some(adjacent_block) => self.is_block_face_visible(adjacent_block), - None => true, + .filter(|direction| { + self.is_block_face_visible(adjacent_blocks.get_for_direction(*direction)) }) .collect::() } @@ -90,11 +92,10 @@ impl WorldBlock { mod tests { use crate::{ block::{BlockData, BlockType}, - direction::Direction, - positions::WorldPos, - world::world_block::WorldBlock, + components::world_pos::WorldPos, + geometry::direction::Direction, + world::{world_block::WorldBlock, AdjacentBlocks}, }; - use std::collections::HashMap; #[test] fn is_block_face_visible() { @@ -133,24 +134,21 @@ mod tests { world_pos: WorldPos { x: 0, y: 0, z: 0 }, }; - let adjacent_blocks = HashMap::new(); + let adjacent_blocks = AdjacentBlocks::new(); - let faces = world_block.get_visible_faces(adjacent_blocks); + let faces = world_block.get_visible_faces(&adjacent_blocks); assert_eq!(faces.into_iter().len(), 6); - let mut adjacent_blocks: HashMap = HashMap::new(); + let mut adjacent_blocks = AdjacentBlocks::new(); - adjacent_blocks.insert( - Direction::East, - WorldBlock { - block_type: BlockType::Cloud, - extra_data: BlockData::None, - world_pos: WorldPos { x: 0, y: 0, z: 0 }, - }, - ); + adjacent_blocks.data[Direction::East.to_index()] = WorldBlock { + block_type: BlockType::Cloud, + extra_data: BlockData::None, + world_pos: WorldPos { x: 0, y: 0, z: 0 }, + }; - let faces = world_block.get_visible_faces(adjacent_blocks); + let faces = world_block.get_visible_faces(&adjacent_blocks); assert_eq!(faces.into_iter().len(), 5); assert_eq!(faces.has_direction(Direction::East), false); diff --git a/lib/world/src/world/world_chunk.rs b/lib/world/src/world/world_chunk.rs index 6ed2b8f..2d3ad5e 100644 --- a/lib/world/src/world/world_chunk.rs +++ b/lib/world/src/world/world_chunk.rs @@ -1,10 +1,16 @@ -use std::collections::HashSet; +use wasm_bindgen::prelude::wasm_bindgen; use super::{ChunkNotLoadedError, World, WorldStateDiff}; use crate::{ - chunk::{chunk_mesh::ChunkMesh, Chunk}, - positions::{ChunkPos, WorldPos}, + chunk::{ + chunk::{Chunk, ChunkId}, + chunk_mesh::ChunkMesh, + chunk_pos::ChunkPos, + }, + components::world_pos::WorldPos, + game::Game, }; +use std::collections::HashSet; impl World { pub fn get_chunk(&self, chunk_pos: &ChunkPos) -> Result<&Chunk, ChunkNotLoadedError> { @@ -13,6 +19,10 @@ impl World { .ok_or(ChunkNotLoadedError) } + pub fn chunk_count(&self) -> usize { + self.chunks.len() + } + pub fn has_chunk(&self, chunk_pos: &ChunkPos) -> bool { self.chunks.contains_key(&chunk_pos.to_world_index()) } @@ -24,6 +34,10 @@ impl World { self.get_chunk(&world_pos.to_chunk_pos()) } + pub fn get_all_chunk_ids(&self) -> HashSet { + self.chunks.keys().map(|&k| k as u64).collect() + } + pub fn get_mut_chunk( &mut self, chunk_pos: &ChunkPos, @@ -35,13 +49,13 @@ impl World { pub fn insert_chunk(&mut self, chunk: Chunk) -> WorldStateDiff { // Update adjacent chunk meshes - let updated_chunk_ids: HashSet = chunk + let updated_chunk_ids: HashSet = chunk .position .get_adjacent_vecs() .iter() .filter_map(|chunk_pos| { if self.update_chunk_mesh(chunk_pos).is_ok() { - Some(chunk_pos.to_index()) + Some(chunk_pos.to_id()) } else { None } @@ -70,14 +84,41 @@ impl World { self.chunks.insert(index.to_owned(), chunk); self.chunks.get_mut(&index.to_owned()).unwrap() } + + pub fn get_loaded_chunk_ids(&self) -> Vec { + let keys = self + .chunks + .values() + .map(|c| c.position.to_id()) + .collect::>(); + keys + } +} + +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "getLoadedChunkids")] + pub fn get_loaded_chunkids_wasm(&self) -> Vec { + self.world.get_loaded_chunk_ids() + } + + #[wasm_bindgen(js_name = "getChunk")] + pub fn get_chunk_wasm(&self, chunk_pos: &ChunkPos) -> Result { + let chunk = self.world.get_chunk(chunk_pos)?; + Ok(chunk.to_owned()) + } } #[cfg(test)] mod tests { + use std::time::{Duration, Instant}; + use crate::{ block::{BlockData, BlockType, ChunkBlock}, - chunk::Chunk, - positions::{ChunkPos, InnerChunkPos, WorldPos}, + chunk::{chunk::Chunk, chunk_pos::ChunkPos, inner_chunk_pos::InnerChunkPos}, + components::world_pos::WorldPos, + geometry::vec::Vector3Ops, + terrain_gen::TerrainGenerator, world::{world_block::WorldBlock, World}, }; @@ -113,7 +154,7 @@ mod tests { let block_pos = WorldPos::new(0, 0, 0); - let chunk = Chunk::new(ChunkPos { x: 0, y: 0 }); + let chunk = Chunk::new(ChunkPos::new(0, 0)); // In the first chunk world.insert_chunk(chunk); @@ -132,7 +173,7 @@ mod tests { assert_eq!(block.extra_data, BlockData::None); // In a different chunk - let chunk2 = Chunk::new(ChunkPos { x: 1, y: 0 }); + let chunk2 = Chunk::new(ChunkPos::new(1, 0)); let block_pos = WorldPos::new(16, 0, 0); let world_block = WorldBlock { @@ -150,4 +191,32 @@ mod tests { assert_eq!(block.block_type, BlockType::Gold); assert_eq!(block.extra_data, BlockData::None); } + + #[test] + fn profile_chunk_insertion() { + // Average time: 32.633088ms + // Max time: 50.154277ms + + // New + // Average time: 20.878063ms + // Max time: 31.049449ms + + let terrain_gen = TerrainGenerator::default(); + + let mut times = Vec::new(); + for _ in 0..500 { + let start_time = Instant::now(); + let mut world = World::default(); + let chunk_pos = ChunkPos::new(0, 0); + let chunk = terrain_gen.get_chunk(chunk_pos.x, chunk_pos.y); + world.insert_chunk(chunk); + times.push(start_time.elapsed()); + } + + println!( + "Average time: {:?}", + times.iter().sum::() / times.len() as u32 + ); + println!("Max time: {:?}", times.iter().max().unwrap()); + } } diff --git a/lib/world/src/world/world_duct.rs b/lib/world/src/world/world_duct.rs index 3cbd1fd..4767b0f 100644 --- a/lib/world/src/world/world_duct.rs +++ b/lib/world/src/world/world_duct.rs @@ -1,9 +1,8 @@ use super::World; use crate::{ - chunk::Chunk, - direction::Directions, - geometry::ray::Ray, - world::{world_block::WorldBlock, ChunkPos, WorldPos}, + chunk::{chunk::Chunk, chunk::ChunkId, chunk_pos::ChunkPos}, + geometry::{direction::Directions, ray::Ray}, + world::{world_block::WorldBlock, WorldPos}, }; use serde_wasm_bindgen::{from_value, to_value, Error}; use wasm_bindgen::prelude::*; @@ -68,20 +67,22 @@ impl World { }) } - pub fn get_chunk_mesh_wasm(&self, val: JsValue) -> Result { - from_value(val).and_then(|pos: ChunkPos| { - let mesh = self.get_chunk_mesh(&pos).map_err(Self::convert_error)?; + pub fn get_chunk_mesh_wasm(&self, chunk_id: ChunkId) -> Result { + let chunk_pos = ChunkPos::from_id(chunk_id); - let wasm_chunk_mesh = mesh - .into_iter() - .map(|(world_pos, directions)| { - let block = self.get_block(&world_pos); - (block, directions.to_owned()) - }) - .collect::>(); + let mesh = self + .get_chunk_mesh(&chunk_pos) + .map_err(Self::convert_error)?; - to_value(&wasm_chunk_mesh) - }) + let wasm_chunk_mesh = mesh + .into_iter() + .map(|(world_pos, directions)| { + let block = self.get_block(&world_pos); + (block, directions.to_owned()) + }) + .collect::>(); + + to_value(&wasm_chunk_mesh) } pub fn is_block_loaded_wasm(&self, val: JsValue) -> Result { @@ -108,6 +109,10 @@ impl World { }) } + pub fn deserialize_wasm(value: JsValue) -> Result { + from_value(value) + } + pub fn has_chunk_wasm(&self, value: JsValue) -> bool { from_value(value) .map(|pos: ChunkPos| self.has_chunk(&pos)) diff --git a/lib/world/src/world/world_mesh.rs b/lib/world/src/world/world_mesh.rs index c6b5d02..8a13342 100644 --- a/lib/world/src/world/world_mesh.rs +++ b/lib/world/src/world/world_mesh.rs @@ -1,9 +1,19 @@ use std::collections::HashSet; +use wasm_bindgen::prelude::wasm_bindgen; + use super::{ChunkNotLoadedError, World, WorldStateDiff}; use crate::{ - chunk::chunk_mesh::{BlockMesh, ChunkMesh}, - positions::{ChunkPos, WorldPos}, + chunk::chunk_pos::ChunkPos, + chunk::{ + chunk::ChunkId, + chunk_mesh::{BlockMesh, ChunkMesh}, + }, + components::world_pos::WorldPos, + game::Game, + geometry::direction::{DirectionVectorExtension, Directions}, + geometry::vec::Vector3Ops, + world::AdjacentBlocks, }; impl World { @@ -12,7 +22,7 @@ impl World { let adj_blocks = self.get_adjacent_blocks(&world_pos); - let faces = world_block.get_visible_faces(adj_blocks); + let faces = world_block.get_visible_faces(&adj_blocks); let chunk_mesh = self.get_chunk_mesh_mut(&world_pos.to_chunk_pos())?; @@ -42,11 +52,32 @@ impl World { } pub fn update_chunk_mesh(&mut self, chunk_pos: &ChunkPos) -> Result<(), ChunkNotLoadedError> { + let mut new_chunk_mesh = ChunkMesh::new(*chunk_pos); let chunk = self.get_chunk(chunk_pos)?; - for block in chunk.get_all_blocks_and_dirty() { - self.update_mesh_at_pos(block.pos.to_world_pos(chunk_pos)) - .ok(); + let all_world_blocks = chunk.get_all_world_blocks_and_dirty(); + + for world_block in all_world_blocks.iter() { + let world_pos = world_block.world_pos; + let mut adjacent_blocks = AdjacentBlocks::new(); + for direction in Directions::all() { + let adjacent_pos = world_pos.move_direction(&direction); + if !adjacent_pos.is_valid() { + continue; + } + + let adjacent_block = if adjacent_pos.to_chunk_pos() == *chunk_pos { + chunk.get_world_block(&adjacent_pos.to_inner_chunk_pos()) + } else { + self.get_block(&adjacent_pos) + }; + + adjacent_blocks.data[direction.to_index()] = adjacent_block; + } + let faces = world_block.get_visible_faces(&adjacent_blocks); + new_chunk_mesh.insert(world_pos, faces); } + self.chunk_meshes + .insert(chunk_pos.to_world_index(), new_chunk_mesh); Ok(()) } @@ -57,7 +88,7 @@ impl World { pub fn update_chunks_around_block(&mut self, world_pos: &WorldPos) -> WorldStateDiff { // Check to see if any of the adjacent blocks are in different chunks. // Don't need to filter out duplicates since they aren't possible - let updated_ids: HashSet = world_pos + let updated_ids: HashSet = world_pos .get_cross_vecs() .iter() // Map to chunk id @@ -66,7 +97,7 @@ impl World { .filter_map(|chunk_pos: ChunkPos| { // Forget about the result, if the chunk isn't loaded, it doesn't matter if self.update_chunk_mesh(&chunk_pos).is_ok() { - Some(chunk_pos.to_index()) + Some(chunk_pos.to_id()) } else { None } @@ -79,20 +110,50 @@ impl World { } } +#[wasm_bindgen] +pub struct FaceEntry { + pub index: usize, + pub directions: Directions, +} + +#[wasm_bindgen] +impl Game { + #[wasm_bindgen(js_name = "getChunkMeshByChunkId")] + pub fn get_chunk_mesh_js( + &self, + chunk_id: ChunkId, + ) -> Result, ChunkNotLoadedError> { + let chunk_pos = ChunkPos::from_id(chunk_id); + let mesh = self.world.get_chunk_mesh(&chunk_pos)?; + Ok(mesh + .face_map + .iter() + // filter out empty directions + .filter(|(_, directions)| directions.into_iter().len() > 0) + .map(|(index, directions)| FaceEntry { + index: *index, + directions: *directions, + }) + .collect()) + } +} + #[cfg(test)] mod tests { use crate::{ block::{BlockData, BlockType}, - chunk::{chunk_mesh::BlockMesh, Chunk}, - direction::{Direction, Directions}, - positions::{ChunkPos, WorldPos}, + chunk::chunk_pos::ChunkPos, + chunk::{chunk::Chunk, chunk_mesh::BlockMesh}, + components::world_pos::WorldPos, + geometry::direction::{Direction, Directions}, + geometry::vec::Vector3Ops, world::{world_block::WorldBlock, World}, }; #[test] fn calculate_chunk_mesh() { let mut world = World::default(); - let mut chunk = Chunk::new(ChunkPos { x: 0, y: 0 }); + let chunk = Chunk::new(ChunkPos { x: 0, y: 0 }); let world_pos = WorldPos::new(0, 0, 0); @@ -121,7 +182,7 @@ mod tests { #[test] fn calculate_chunk_mesh_with_adjacent_block() { let mut world = World::default(); - let mut chunk = Chunk::new(ChunkPos { x: 0, y: 0 }); + let chunk = Chunk::new(ChunkPos { x: 0, y: 0 }); let world_pos = WorldPos::new(0, 0, 0); let adjacent_world_pos = WorldPos::new(0, 0, 1); @@ -160,7 +221,7 @@ mod tests { #[test] fn calculate_chunk_mesh_with_adjacent_block_south() { let mut world = World::default(); - let mut chunk = Chunk::new(ChunkPos { x: 0, y: 0 }); + let chunk = Chunk::new(ChunkPos { x: 0, y: 0 }); let world_pos = WorldPos::new(0, 0, 1); let adjacent_world_pos = WorldPos::new(0, 0, 0); diff --git a/yarn.lock b/yarn.lock index 0a997af..ff5ae1c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,7 +5,7 @@ __metadata: version: 8 cacheKey: 10 -"@ampproject/remapping@npm:^2.2.0": +"@ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.3.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" dependencies: @@ -15,1149 +15,700 @@ __metadata: languageName: node linkType: hard -"@aws-crypto/crc32@npm:3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/crc32@npm:3.0.0" - dependencies: - "@aws-crypto/util": "npm:^3.0.0" - "@aws-sdk/types": "npm:^3.222.0" - tslib: "npm:^1.11.1" - checksum: 10/672d593fd98a88709a1b488db92aabf584b6dad3e8099e04b6d2870e34a2ee668cbbe0e5406e60c0d776b9c34a91cfc427999230ad959518fed56a3db037704c - languageName: node - linkType: hard - -"@aws-crypto/ie11-detection@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/ie11-detection@npm:3.0.0" - dependencies: - tslib: "npm:^1.11.1" - checksum: 10/f5aee4a11a113ab9640474e75d398c99538aa30775f484cd519f0de0096ae0d4a6b68d2f0c685f24bd6f2425067c565bc20592c36c0dc1f4d28c1b4751a40734 - languageName: node - linkType: hard - -"@aws-crypto/sha256-browser@npm:3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/sha256-browser@npm:3.0.0" +"@aws-crypto/sha256-browser@npm:5.2.0": + version: 5.2.0 + resolution: "@aws-crypto/sha256-browser@npm:5.2.0" dependencies: - "@aws-crypto/ie11-detection": "npm:^3.0.0" - "@aws-crypto/sha256-js": "npm:^3.0.0" - "@aws-crypto/supports-web-crypto": "npm:^3.0.0" - "@aws-crypto/util": "npm:^3.0.0" + "@aws-crypto/sha256-js": "npm:^5.2.0" + "@aws-crypto/supports-web-crypto": "npm:^5.2.0" + "@aws-crypto/util": "npm:^5.2.0" "@aws-sdk/types": "npm:^3.222.0" "@aws-sdk/util-locate-window": "npm:^3.0.0" - "@aws-sdk/util-utf8-browser": "npm:^3.0.0" - tslib: "npm:^1.11.1" - checksum: 10/4e075906c48a46bbb8babb60db3e6b280db405a88c68b77c1496c26218292d5ea509beae3ccc19366ca6bc944c6d37fe347d0917909900dbac86f054a19c71c7 + "@smithy/util-utf8": "npm:^2.0.0" + tslib: "npm:^2.6.2" + checksum: 10/2b1b701ca6caa876333b4eb2b96e5187d71ebb51ebf8e2d632690dbcdedeff038202d23adcc97e023437ed42bb1963b7b463e343687edf0635fd4b98b2edad1a languageName: node linkType: hard -"@aws-crypto/sha256-js@npm:3.0.0, @aws-crypto/sha256-js@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/sha256-js@npm:3.0.0" +"@aws-crypto/sha256-js@npm:5.2.0, @aws-crypto/sha256-js@npm:^5.2.0": + version: 5.2.0 + resolution: "@aws-crypto/sha256-js@npm:5.2.0" dependencies: - "@aws-crypto/util": "npm:^3.0.0" + "@aws-crypto/util": "npm:^5.2.0" "@aws-sdk/types": "npm:^3.222.0" - tslib: "npm:^1.11.1" - checksum: 10/f9fc2d51631950434d0f91f51c2ce17845d4e8e75971806e21604987e3186ee1e54de8a89e5349585b91cb36e56d5f058d6a45004e1bfbce1351dbb40f479152 + tslib: "npm:^2.6.2" + checksum: 10/f46aace7b873c615be4e787ab0efd0148ef7de48f9f12c7d043e05c52e52b75bb0bf6dbcb9b2852d940d7724fab7b6d5ff1469160a3dd024efe7a68b5f70df8c languageName: node linkType: hard -"@aws-crypto/supports-web-crypto@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/supports-web-crypto@npm:3.0.0" +"@aws-crypto/supports-web-crypto@npm:^5.2.0": + version: 5.2.0 + resolution: "@aws-crypto/supports-web-crypto@npm:5.2.0" dependencies: - tslib: "npm:^1.11.1" - checksum: 10/8a48788d2866e391354f256aa79b577b2ba1474b50184cbe690467de7e64a79928afece95007ab69a1556f99da97ea129487db091d94489847e14decdc7c9a6f + tslib: "npm:^2.6.2" + checksum: 10/6ed0c7e17f4f6663d057630805c45edb35d5693380c24ab52d4c453ece303c6c8a6ade9ee93c97dda77d9f6cae376ffbb44467057161c513dffa3422250edaf5 languageName: node linkType: hard -"@aws-crypto/util@npm:^3.0.0": - version: 3.0.0 - resolution: "@aws-crypto/util@npm:3.0.0" +"@aws-crypto/util@npm:^5.2.0": + version: 5.2.0 + resolution: "@aws-crypto/util@npm:5.2.0" dependencies: "@aws-sdk/types": "npm:^3.222.0" - "@aws-sdk/util-utf8-browser": "npm:^3.0.0" - tslib: "npm:^1.11.1" - checksum: 10/92c835b83d7a888b37b2f2a37c82e58bb8fabb617e371173c488d2a71b916c69ee566f0ea0b3f7f4e16296226c49793f95b3d59fc07a7ca00af91f8f9f29e6c4 - languageName: node - linkType: hard - -"@aws-sdk/abort-controller@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/abort-controller@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/7bce9589e601628ce89ed3254693345ee222c3c77d662f8121a85747dfb049f46cce340925bac65d62d2fb03770543ac74f8c470a7f6bdd39f32a50641b064d3 - languageName: node - linkType: hard - -"@aws-sdk/client-cognito-identity@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/client-cognito-identity@npm:3.350.0" - dependencies: - "@aws-crypto/sha256-browser": "npm:3.0.0" - "@aws-crypto/sha256-js": "npm:3.0.0" - "@aws-sdk/client-sts": "npm:3.350.0" - "@aws-sdk/config-resolver": "npm:3.347.0" - "@aws-sdk/credential-provider-node": "npm:3.350.0" - "@aws-sdk/fetch-http-handler": "npm:3.347.0" - "@aws-sdk/hash-node": "npm:3.347.0" - "@aws-sdk/invalid-dependency": "npm:3.347.0" - "@aws-sdk/middleware-content-length": "npm:3.347.0" - "@aws-sdk/middleware-endpoint": "npm:3.347.0" - "@aws-sdk/middleware-host-header": "npm:3.347.0" - "@aws-sdk/middleware-logger": "npm:3.347.0" - "@aws-sdk/middleware-recursion-detection": "npm:3.347.0" - "@aws-sdk/middleware-retry": "npm:3.347.0" - "@aws-sdk/middleware-serde": "npm:3.347.0" - "@aws-sdk/middleware-signing": "npm:3.347.0" - "@aws-sdk/middleware-stack": "npm:3.347.0" - "@aws-sdk/middleware-user-agent": "npm:3.347.0" - "@aws-sdk/node-config-provider": "npm:3.347.0" - "@aws-sdk/node-http-handler": "npm:3.350.0" - "@aws-sdk/smithy-client": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/url-parser": "npm:3.347.0" - "@aws-sdk/util-base64": "npm:3.310.0" - "@aws-sdk/util-body-length-browser": "npm:3.310.0" - "@aws-sdk/util-body-length-node": "npm:3.310.0" - "@aws-sdk/util-defaults-mode-browser": "npm:3.347.0" - "@aws-sdk/util-defaults-mode-node": "npm:3.347.0" - "@aws-sdk/util-endpoints": "npm:3.347.0" - "@aws-sdk/util-retry": "npm:3.347.0" - "@aws-sdk/util-user-agent-browser": "npm:3.347.0" - "@aws-sdk/util-user-agent-node": "npm:3.347.0" - "@aws-sdk/util-utf8": "npm:3.310.0" - "@smithy/protocol-http": "npm:^1.0.1" - "@smithy/types": "npm:^1.0.0" - tslib: "npm:^2.5.0" - checksum: 10/7031979d8380e90525c835e7e1db704acb323681d2588ecabf07b2e49f055e3b3e65a57a0ae2f80476ecf232f156b8afb7079fd28c228676d87a2acdbe7948a3 - languageName: node - linkType: hard - -"@aws-sdk/client-sso-oidc@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/client-sso-oidc@npm:3.350.0" - dependencies: - "@aws-crypto/sha256-browser": "npm:3.0.0" - "@aws-crypto/sha256-js": "npm:3.0.0" - "@aws-sdk/config-resolver": "npm:3.347.0" - "@aws-sdk/fetch-http-handler": "npm:3.347.0" - "@aws-sdk/hash-node": "npm:3.347.0" - "@aws-sdk/invalid-dependency": "npm:3.347.0" - "@aws-sdk/middleware-content-length": "npm:3.347.0" - "@aws-sdk/middleware-endpoint": "npm:3.347.0" - "@aws-sdk/middleware-host-header": "npm:3.347.0" - "@aws-sdk/middleware-logger": "npm:3.347.0" - "@aws-sdk/middleware-recursion-detection": "npm:3.347.0" - "@aws-sdk/middleware-retry": "npm:3.347.0" - "@aws-sdk/middleware-serde": "npm:3.347.0" - "@aws-sdk/middleware-stack": "npm:3.347.0" - "@aws-sdk/middleware-user-agent": "npm:3.347.0" - "@aws-sdk/node-config-provider": "npm:3.347.0" - "@aws-sdk/node-http-handler": "npm:3.350.0" - "@aws-sdk/smithy-client": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/url-parser": "npm:3.347.0" - "@aws-sdk/util-base64": "npm:3.310.0" - "@aws-sdk/util-body-length-browser": "npm:3.310.0" - "@aws-sdk/util-body-length-node": "npm:3.310.0" - "@aws-sdk/util-defaults-mode-browser": "npm:3.347.0" - "@aws-sdk/util-defaults-mode-node": "npm:3.347.0" - "@aws-sdk/util-endpoints": "npm:3.347.0" - "@aws-sdk/util-retry": "npm:3.347.0" - "@aws-sdk/util-user-agent-browser": "npm:3.347.0" - "@aws-sdk/util-user-agent-node": "npm:3.347.0" - "@aws-sdk/util-utf8": "npm:3.310.0" - "@smithy/protocol-http": "npm:^1.0.1" - "@smithy/types": "npm:^1.0.0" - tslib: "npm:^2.5.0" - checksum: 10/af0573ad1c47de247e55fa158b92f4d3e92c1fa8ef5bec7cd6d8f8c6e676bf5b7a9fad3dd7c67596db763da587d925ea9f4668ae6d42d7846373133597a4aecd - languageName: node - linkType: hard - -"@aws-sdk/client-sso@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/client-sso@npm:3.350.0" - dependencies: - "@aws-crypto/sha256-browser": "npm:3.0.0" - "@aws-crypto/sha256-js": "npm:3.0.0" - "@aws-sdk/config-resolver": "npm:3.347.0" - "@aws-sdk/fetch-http-handler": "npm:3.347.0" - "@aws-sdk/hash-node": "npm:3.347.0" - "@aws-sdk/invalid-dependency": "npm:3.347.0" - "@aws-sdk/middleware-content-length": "npm:3.347.0" - "@aws-sdk/middleware-endpoint": "npm:3.347.0" - "@aws-sdk/middleware-host-header": "npm:3.347.0" - "@aws-sdk/middleware-logger": "npm:3.347.0" - "@aws-sdk/middleware-recursion-detection": "npm:3.347.0" - "@aws-sdk/middleware-retry": "npm:3.347.0" - "@aws-sdk/middleware-serde": "npm:3.347.0" - "@aws-sdk/middleware-stack": "npm:3.347.0" - "@aws-sdk/middleware-user-agent": "npm:3.347.0" - "@aws-sdk/node-config-provider": "npm:3.347.0" - "@aws-sdk/node-http-handler": "npm:3.350.0" - "@aws-sdk/smithy-client": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/url-parser": "npm:3.347.0" - "@aws-sdk/util-base64": "npm:3.310.0" - "@aws-sdk/util-body-length-browser": "npm:3.310.0" - "@aws-sdk/util-body-length-node": "npm:3.310.0" - "@aws-sdk/util-defaults-mode-browser": "npm:3.347.0" - "@aws-sdk/util-defaults-mode-node": "npm:3.347.0" - "@aws-sdk/util-endpoints": "npm:3.347.0" - "@aws-sdk/util-retry": "npm:3.347.0" - "@aws-sdk/util-user-agent-browser": "npm:3.347.0" - "@aws-sdk/util-user-agent-node": "npm:3.347.0" - "@aws-sdk/util-utf8": "npm:3.310.0" - "@smithy/protocol-http": "npm:^1.0.1" - "@smithy/types": "npm:^1.0.0" - tslib: "npm:^2.5.0" - checksum: 10/0da663b0bc6f67ee3ed704b9e244d0c1bea959cfe2d1c86b631e152c2377ccd5642d63509a6c00202b0076d72c0d07e69fa58103e836009fc9069e394416135d - languageName: node - linkType: hard - -"@aws-sdk/client-sts@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/client-sts@npm:3.350.0" - dependencies: - "@aws-crypto/sha256-browser": "npm:3.0.0" - "@aws-crypto/sha256-js": "npm:3.0.0" - "@aws-sdk/config-resolver": "npm:3.347.0" - "@aws-sdk/credential-provider-node": "npm:3.350.0" - "@aws-sdk/fetch-http-handler": "npm:3.347.0" - "@aws-sdk/hash-node": "npm:3.347.0" - "@aws-sdk/invalid-dependency": "npm:3.347.0" - "@aws-sdk/middleware-content-length": "npm:3.347.0" - "@aws-sdk/middleware-endpoint": "npm:3.347.0" - "@aws-sdk/middleware-host-header": "npm:3.347.0" - "@aws-sdk/middleware-logger": "npm:3.347.0" - "@aws-sdk/middleware-recursion-detection": "npm:3.347.0" - "@aws-sdk/middleware-retry": "npm:3.347.0" - "@aws-sdk/middleware-sdk-sts": "npm:3.347.0" - "@aws-sdk/middleware-serde": "npm:3.347.0" - "@aws-sdk/middleware-signing": "npm:3.347.0" - "@aws-sdk/middleware-stack": "npm:3.347.0" - "@aws-sdk/middleware-user-agent": "npm:3.347.0" - "@aws-sdk/node-config-provider": "npm:3.347.0" - "@aws-sdk/node-http-handler": "npm:3.350.0" - "@aws-sdk/smithy-client": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/url-parser": "npm:3.347.0" - "@aws-sdk/util-base64": "npm:3.310.0" - "@aws-sdk/util-body-length-browser": "npm:3.310.0" - "@aws-sdk/util-body-length-node": "npm:3.310.0" - "@aws-sdk/util-defaults-mode-browser": "npm:3.347.0" - "@aws-sdk/util-defaults-mode-node": "npm:3.347.0" - "@aws-sdk/util-endpoints": "npm:3.347.0" - "@aws-sdk/util-retry": "npm:3.347.0" - "@aws-sdk/util-user-agent-browser": "npm:3.347.0" - "@aws-sdk/util-user-agent-node": "npm:3.347.0" - "@aws-sdk/util-utf8": "npm:3.310.0" - "@smithy/protocol-http": "npm:^1.0.1" - "@smithy/types": "npm:^1.0.0" - fast-xml-parser: "npm:4.2.4" - tslib: "npm:^2.5.0" - checksum: 10/9b7a5e23c82915546e07a8bec6cda4b9ad905e41f37ba4547883ec27c6ffde0fee4753eae2d5446a9d6831a9015b4d088248ea2441516753ba9635abd6e72f8a - languageName: node - linkType: hard - -"@aws-sdk/config-resolver@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/config-resolver@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-config-provider": "npm:3.310.0" - "@aws-sdk/util-middleware": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/4709deafbf1eb5af5142435dd5c4b47b6e614e7287445bdf6e322ddfbc396f4dc4efaa1c8d690a7d8449d3cef2e314bf942c4ffecc94dfd27e643c4c2705bc51 - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-cognito-identity@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.350.0" - dependencies: - "@aws-sdk/client-cognito-identity": "npm:3.350.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/edad650da30779a22bc3c46f96f0a40e62b780986ea2deabf759755245c377c16aeee2d4802e64d5a66ab295a5dc28db99cf0ec498fd1f89eb06c76ac652e4e3 - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-env@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/credential-provider-env@npm:3.347.0" - dependencies: - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/41f8669df7ef56a82016e77d3e05fe7e0f6670ff296a9cab4474f90e21b7663929bd4db496529c0e5f0cd86248dd45b72f1545ab74685c51b2ebf38d57a9d716 - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-imds@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/credential-provider-imds@npm:3.347.0" - dependencies: - "@aws-sdk/node-config-provider": "npm:3.347.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/url-parser": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/9b8e63f636f1418fd041da450cce7f79bbe50049be68fc16b2667ebc438444f8fc2bc9eee2f1d1799d0b3f143010ac1d021f9511465c9003e43bcf61632d03b5 - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-ini@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/credential-provider-ini@npm:3.350.0" - dependencies: - "@aws-sdk/credential-provider-env": "npm:3.347.0" - "@aws-sdk/credential-provider-imds": "npm:3.347.0" - "@aws-sdk/credential-provider-process": "npm:3.347.0" - "@aws-sdk/credential-provider-sso": "npm:3.350.0" - "@aws-sdk/credential-provider-web-identity": "npm:3.347.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/shared-ini-file-loader": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/3d3fe05907247674a2a55ecf66ac658c61b76b4dedb78e0b95f991e6753a736b265e1ff58da9913a5b9afca115b1cd3b0e8d47036290e336f743dfae0c551a7e - languageName: node - linkType: hard - -"@aws-sdk/credential-provider-node@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/credential-provider-node@npm:3.350.0" - dependencies: - "@aws-sdk/credential-provider-env": "npm:3.347.0" - "@aws-sdk/credential-provider-imds": "npm:3.347.0" - "@aws-sdk/credential-provider-ini": "npm:3.350.0" - "@aws-sdk/credential-provider-process": "npm:3.347.0" - "@aws-sdk/credential-provider-sso": "npm:3.350.0" - "@aws-sdk/credential-provider-web-identity": "npm:3.347.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/shared-ini-file-loader": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/38106859b2c870cd315e7048b640ab04fdb2026eb0251dcb3ecb644356bb6194e00a45503b26a41e12e1f25d9cbe70abdec6610e1ad131dcabb83d6dd2191593 + "@smithy/util-utf8": "npm:^2.0.0" + tslib: "npm:^2.6.2" + checksum: 10/f80a174c404e1ad4364741c942f440e75f834c08278fa754349fe23a6edc679d480ea9ced5820774aee58091ed270067022d8059ecf1a7ef452d58134ac7e9e1 + languageName: node + linkType: hard + +"@aws-sdk/client-cognito-identity@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/client-cognito-identity@npm:3.817.0" + dependencies: + "@aws-crypto/sha256-browser": "npm:5.2.0" + "@aws-crypto/sha256-js": "npm:5.2.0" + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/credential-provider-node": "npm:3.817.0" + "@aws-sdk/middleware-host-header": "npm:3.804.0" + "@aws-sdk/middleware-logger": "npm:3.804.0" + "@aws-sdk/middleware-recursion-detection": "npm:3.804.0" + "@aws-sdk/middleware-user-agent": "npm:3.816.0" + "@aws-sdk/region-config-resolver": "npm:3.808.0" + "@aws-sdk/types": "npm:3.804.0" + "@aws-sdk/util-endpoints": "npm:3.808.0" + "@aws-sdk/util-user-agent-browser": "npm:3.804.0" + "@aws-sdk/util-user-agent-node": "npm:3.816.0" + "@smithy/config-resolver": "npm:^4.1.2" + "@smithy/core": "npm:^3.3.3" + "@smithy/fetch-http-handler": "npm:^5.0.2" + "@smithy/hash-node": "npm:^4.0.2" + "@smithy/invalid-dependency": "npm:^4.0.2" + "@smithy/middleware-content-length": "npm:^4.0.2" + "@smithy/middleware-endpoint": "npm:^4.1.6" + "@smithy/middleware-retry": "npm:^4.1.7" + "@smithy/middleware-serde": "npm:^4.0.5" + "@smithy/middleware-stack": "npm:^4.0.2" + "@smithy/node-config-provider": "npm:^4.1.1" + "@smithy/node-http-handler": "npm:^4.0.4" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/smithy-client": "npm:^4.2.6" + "@smithy/types": "npm:^4.2.0" + "@smithy/url-parser": "npm:^4.0.2" + "@smithy/util-base64": "npm:^4.0.0" + "@smithy/util-body-length-browser": "npm:^4.0.0" + "@smithy/util-body-length-node": "npm:^4.0.0" + "@smithy/util-defaults-mode-browser": "npm:^4.0.14" + "@smithy/util-defaults-mode-node": "npm:^4.0.14" + "@smithy/util-endpoints": "npm:^3.0.4" + "@smithy/util-middleware": "npm:^4.0.2" + "@smithy/util-retry": "npm:^4.0.3" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/95670ae5b13e4af9729d7dce919dab202a103f3650c3db28f9658d4d40b37dfb9802eb245e8bb7c63a23f3b0567cd6a4c935e2417697d6577a485d07edd6a7c1 + languageName: node + linkType: hard + +"@aws-sdk/client-sso@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/client-sso@npm:3.817.0" + dependencies: + "@aws-crypto/sha256-browser": "npm:5.2.0" + "@aws-crypto/sha256-js": "npm:5.2.0" + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/middleware-host-header": "npm:3.804.0" + "@aws-sdk/middleware-logger": "npm:3.804.0" + "@aws-sdk/middleware-recursion-detection": "npm:3.804.0" + "@aws-sdk/middleware-user-agent": "npm:3.816.0" + "@aws-sdk/region-config-resolver": "npm:3.808.0" + "@aws-sdk/types": "npm:3.804.0" + "@aws-sdk/util-endpoints": "npm:3.808.0" + "@aws-sdk/util-user-agent-browser": "npm:3.804.0" + "@aws-sdk/util-user-agent-node": "npm:3.816.0" + "@smithy/config-resolver": "npm:^4.1.2" + "@smithy/core": "npm:^3.3.3" + "@smithy/fetch-http-handler": "npm:^5.0.2" + "@smithy/hash-node": "npm:^4.0.2" + "@smithy/invalid-dependency": "npm:^4.0.2" + "@smithy/middleware-content-length": "npm:^4.0.2" + "@smithy/middleware-endpoint": "npm:^4.1.6" + "@smithy/middleware-retry": "npm:^4.1.7" + "@smithy/middleware-serde": "npm:^4.0.5" + "@smithy/middleware-stack": "npm:^4.0.2" + "@smithy/node-config-provider": "npm:^4.1.1" + "@smithy/node-http-handler": "npm:^4.0.4" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/smithy-client": "npm:^4.2.6" + "@smithy/types": "npm:^4.2.0" + "@smithy/url-parser": "npm:^4.0.2" + "@smithy/util-base64": "npm:^4.0.0" + "@smithy/util-body-length-browser": "npm:^4.0.0" + "@smithy/util-body-length-node": "npm:^4.0.0" + "@smithy/util-defaults-mode-browser": "npm:^4.0.14" + "@smithy/util-defaults-mode-node": "npm:^4.0.14" + "@smithy/util-endpoints": "npm:^3.0.4" + "@smithy/util-middleware": "npm:^4.0.2" + "@smithy/util-retry": "npm:^4.0.3" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/72e4e1767d444784933d0414a7c6c197d216c8ff6aa760efea97533ec2bd10a9f841d9ef36d19510d644b42d455f0aec63bb97c13b8b4f3bab645c4741ceead2 + languageName: node + linkType: hard + +"@aws-sdk/core@npm:3.816.0": + version: 3.816.0 + resolution: "@aws-sdk/core@npm:3.816.0" + dependencies: + "@aws-sdk/types": "npm:3.804.0" + "@smithy/core": "npm:^3.3.3" + "@smithy/node-config-provider": "npm:^4.1.1" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/signature-v4": "npm:^5.1.0" + "@smithy/smithy-client": "npm:^4.2.6" + "@smithy/types": "npm:^4.2.0" + "@smithy/util-middleware": "npm:^4.0.2" + fast-xml-parser: "npm:4.4.1" + tslib: "npm:^2.6.2" + checksum: 10/2b6c4188969e00af0f4d77ed88b8b23b4654c0e66b3356ae062a0d40ab6831c78db1473efd20514c182f8d4033ce2728b0425a292c57246ceb22a177c17d970f + languageName: node + linkType: hard + +"@aws-sdk/credential-provider-cognito-identity@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.817.0" + dependencies: + "@aws-sdk/client-cognito-identity": "npm:3.817.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/caba36f8c92314016cb71b3ae757142f4f83cc600665341b1ba51a469ccb13dfcef4d5916d228edc25e055aeeb5a7617b2e5e850e8241527fe4cb07bd576a393 + languageName: node + linkType: hard + +"@aws-sdk/credential-provider-env@npm:3.816.0": + version: 3.816.0 + resolution: "@aws-sdk/credential-provider-env@npm:3.816.0" + dependencies: + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/0fcc1f287bfd4daa650b5d72a83c87c031f7b99e1877bd2ff78efc4d756b30e1f69770f2034294da1da05466b961cd4596a848b8e3295d8abf6502abdc48b35f + languageName: node + linkType: hard + +"@aws-sdk/credential-provider-http@npm:3.816.0": + version: 3.816.0 + resolution: "@aws-sdk/credential-provider-http@npm:3.816.0" + dependencies: + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/fetch-http-handler": "npm:^5.0.2" + "@smithy/node-http-handler": "npm:^4.0.4" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/smithy-client": "npm:^4.2.6" + "@smithy/types": "npm:^4.2.0" + "@smithy/util-stream": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/ddc59373a984a1df1cb4efa50027d01dba0d7031b3d0d720edd8bf03d35e4c6ff2333fd8310603c7cc034308124f4f0412e3ca52d7c3d12dad6b0528de11fea0 + languageName: node + linkType: hard + +"@aws-sdk/credential-provider-ini@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/credential-provider-ini@npm:3.817.0" + dependencies: + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/credential-provider-env": "npm:3.816.0" + "@aws-sdk/credential-provider-http": "npm:3.816.0" + "@aws-sdk/credential-provider-process": "npm:3.816.0" + "@aws-sdk/credential-provider-sso": "npm:3.817.0" + "@aws-sdk/credential-provider-web-identity": "npm:3.817.0" + "@aws-sdk/nested-clients": "npm:3.817.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/credential-provider-imds": "npm:^4.0.4" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/shared-ini-file-loader": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/d7c6f44e1dbf2eedb20f45581990136e531975870866573ca2256c325f9ea96264c6e7a45e691622668f034f8d04937c65da5a5ddc18f169f02652ea37c1b7bb + languageName: node + linkType: hard + +"@aws-sdk/credential-provider-node@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/credential-provider-node@npm:3.817.0" + dependencies: + "@aws-sdk/credential-provider-env": "npm:3.816.0" + "@aws-sdk/credential-provider-http": "npm:3.816.0" + "@aws-sdk/credential-provider-ini": "npm:3.817.0" + "@aws-sdk/credential-provider-process": "npm:3.816.0" + "@aws-sdk/credential-provider-sso": "npm:3.817.0" + "@aws-sdk/credential-provider-web-identity": "npm:3.817.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/credential-provider-imds": "npm:^4.0.4" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/shared-ini-file-loader": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/19aee97abcbbd3e84004d2be109c0e05e50947a78f3493ca98cadc1210a597d68eed6ab9a42b188dae8545349ea5e92fc43ae32209799e5e4ab4541df4e85f70 languageName: node linkType: hard -"@aws-sdk/credential-provider-process@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/credential-provider-process@npm:3.347.0" +"@aws-sdk/credential-provider-process@npm:3.816.0": + version: 3.816.0 + resolution: "@aws-sdk/credential-provider-process@npm:3.816.0" dependencies: - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/shared-ini-file-loader": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/f0403438e1238b6513f6b1fb2e226d81c83641e84e0932311db2ae6cbb46852f4a7fdada9a198f39dccc6368bcd8c463695a13b8def29811f057ee0c95e91b3a + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/shared-ini-file-loader": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/f52781ce364a37b7187a10f1f4beb5977e58fc8a2eedb1c67afd6f5cd1f07495be5f928a5aa1731a3b5874d86bb198754d6d81ef5a3b3a4e58bf4c35f16bc479 languageName: node linkType: hard -"@aws-sdk/credential-provider-sso@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/credential-provider-sso@npm:3.350.0" +"@aws-sdk/credential-provider-sso@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/credential-provider-sso@npm:3.817.0" dependencies: - "@aws-sdk/client-sso": "npm:3.350.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/shared-ini-file-loader": "npm:3.347.0" - "@aws-sdk/token-providers": "npm:3.350.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/da6222ad43d56752520b58734b94516782042f39b927a647fe3d24b02f1ca3e835066f7e2f1b306d23eaa0da6d4ada723621c6bc7fe485df9c3240c28d8b707f + "@aws-sdk/client-sso": "npm:3.817.0" + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/token-providers": "npm:3.817.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/shared-ini-file-loader": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/b6fc63d0c7e6582591b30f53250429a9eb6f8e116ec3fce1cff4cb892264ff87d5c69b68a3eea23f1630d63d8a80b544142726a0687f2c76a6533bd58bd6ddec languageName: node - linkType: hard + linkType: hard -"@aws-sdk/credential-provider-web-identity@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/credential-provider-web-identity@npm:3.347.0" +"@aws-sdk/credential-provider-web-identity@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/credential-provider-web-identity@npm:3.817.0" dependencies: - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/f1cb28eb8a6fe13b9f2b12b91af2558cc523fecbb7e965d643fe69773968375a1dfa99b13a8be464239126d65df2c948259ef5c5ce0c72b38592d997f35c7c22 + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/nested-clients": "npm:3.817.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/8b6b3fe7c20e633a576af4a3ae085bc5d858883a78630372082085294f2f37ef951a1f86574981b52dd6946ff49015f61eec4b3e457ef73491563f47b4873389 languageName: node linkType: hard "@aws-sdk/credential-providers@npm:^3.186.0": - version: 3.350.0 - resolution: "@aws-sdk/credential-providers@npm:3.350.0" - dependencies: - "@aws-sdk/client-cognito-identity": "npm:3.350.0" - "@aws-sdk/client-sso": "npm:3.350.0" - "@aws-sdk/client-sts": "npm:3.350.0" - "@aws-sdk/credential-provider-cognito-identity": "npm:3.350.0" - "@aws-sdk/credential-provider-env": "npm:3.347.0" - "@aws-sdk/credential-provider-imds": "npm:3.347.0" - "@aws-sdk/credential-provider-ini": "npm:3.350.0" - "@aws-sdk/credential-provider-node": "npm:3.350.0" - "@aws-sdk/credential-provider-process": "npm:3.347.0" - "@aws-sdk/credential-provider-sso": "npm:3.350.0" - "@aws-sdk/credential-provider-web-identity": "npm:3.347.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/eb342eee88a35bb4037804b46f16fab864cce448e2384127f9fd159ef6db3a8afc57bcd13a995093ff8f1e7032c40b65edcd2c99bba69361ae4684c0507bb3ae - languageName: node - linkType: hard - -"@aws-sdk/eventstream-codec@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/eventstream-codec@npm:3.347.0" - dependencies: - "@aws-crypto/crc32": "npm:3.0.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-hex-encoding": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/9bef859bf6f19a4a5c20103c61a040efb34318e7730122d41161ba473e8a6820276de945fec213c4ce3e4df2349f26bcd7ef2321c85c3b816fb78d17a465fee1 - languageName: node - linkType: hard - -"@aws-sdk/fetch-http-handler@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/fetch-http-handler@npm:3.347.0" - dependencies: - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/querystring-builder": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-base64": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/f5818475d70ed8624c51b06019fb75bd2ab2d6520b9e5f7721079c5003dc57c1e0eda74227c35e8ffebbfe7e496748859fed0bb167eb8f26412a2298c2d6a675 - languageName: node - linkType: hard - -"@aws-sdk/hash-node@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/hash-node@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-buffer-from": "npm:3.310.0" - "@aws-sdk/util-utf8": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/ccfdbcb9b4f6ef2be67057aa96ee20fbd5c2f46d485c5f371d4267ff8a7e075c3dcd3453a085d52bd456310228cf6e5e6921d33cd844266d95bb9be8e1d25167 - languageName: node - linkType: hard - -"@aws-sdk/invalid-dependency@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/invalid-dependency@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/1c0b0c883fd8c090eeccd67545f03c6309928bbfbd24a697d65e286280c3ee467f85d48839a42b9be0aaf6b783505ca8996d7c64caac52bd0d0fd66196e87f63 - languageName: node - linkType: hard - -"@aws-sdk/is-array-buffer@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/is-array-buffer@npm:3.310.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/5d4ed0d6ce00eed0dea61f5ce7ea23ae691ef2fa8c0eea88e0c334fd533483c4892110adb7ae671e7e5c7b26c1b7dcad5560e388fa04947d92e689ffef942340 - languageName: node - linkType: hard - -"@aws-sdk/middleware-content-length@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-content-length@npm:3.347.0" - dependencies: - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/32844e5d95f566d6962676cc973c6d6d5dc4fbeb4d7893857cac46e9a1963426f17e28f298a5a6e142823e619d38a89805f8dc53d705bdb27ae1ef2619528805 - languageName: node - linkType: hard - -"@aws-sdk/middleware-endpoint@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-endpoint@npm:3.347.0" - dependencies: - "@aws-sdk/middleware-serde": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/url-parser": "npm:3.347.0" - "@aws-sdk/util-middleware": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/0b25737da00fce1ea82879a36d1b08c829370f261dfb75f25dd0380027bf60ef4d2d74e62999e3e0e237d8b3cb4501de0830be253ed43de4fb435dfb8ebcd657 - languageName: node - linkType: hard - -"@aws-sdk/middleware-host-header@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-host-header@npm:3.347.0" - dependencies: - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/45e2cd7e0c4a8496294a2a5157b77c5247dd4f338ca319d9711807745f8232cded71f268318d91310788cc669a5e8f7f8d3bc6df36a451882234414d51f7f7df - languageName: node - linkType: hard - -"@aws-sdk/middleware-logger@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-logger@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/ef0e1b8ada4d99390b91dfa6988cf6095fff117744fd7f1bb273d11db8fd6eb85a9ab24bdfbee464c92e0fc20d028c32814eac976932321d4ae5cc3feacc0cf4 - languageName: node - linkType: hard - -"@aws-sdk/middleware-recursion-detection@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-recursion-detection@npm:3.347.0" - dependencies: - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/99c6a7c217fb827c77ea50e38a9faedc5decc8eed369d8a08f238102de955a2ba0fbe30f93fa1a0863f430edf509582c20e9361830264f9e716a0983149459cf - languageName: node - linkType: hard - -"@aws-sdk/middleware-retry@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-retry@npm:3.347.0" - dependencies: - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/service-error-classification": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-middleware": "npm:3.347.0" - "@aws-sdk/util-retry": "npm:3.347.0" - tslib: "npm:^2.5.0" - uuid: "npm:^8.3.2" - checksum: 10/e5f86f05ed80b4f925c525d1058841c94e65586cc7c56552558eb143ba23b8ed8a0b32202fde510134aff66dfe56f9be1c97235c54793a48eb5e6d5f73156129 - languageName: node - linkType: hard - -"@aws-sdk/middleware-sdk-sts@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-sdk-sts@npm:3.347.0" - dependencies: - "@aws-sdk/middleware-signing": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/618928e88ddf7205a1bd402c53ca0e0ed3a3e2d6423c96615c7ec3c6c4f8673f2c06e0eed70fbaac0d57b7c0251b4cf1fc5a2939eff8591e48df0eab2c1e02a9 - languageName: node - linkType: hard - -"@aws-sdk/middleware-serde@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-serde@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/c8909f853958434cdce75114dc128a336de8940150451183e73b3cdebe875de81e4d18e65ea4b342ff8601e21ce75ee6b67315f66a968258abbbc5500da6f389 - languageName: node - linkType: hard - -"@aws-sdk/middleware-signing@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-signing@npm:3.347.0" - dependencies: - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/signature-v4": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-middleware": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/7eaeb9267438669af8a00b6364c10460b87e037b39710c126e9b8b1f2cd562a42768630decbad76e0a8d245520b542fd00cea2ae3a6cd2d712d091c38a2207d6 - languageName: node - linkType: hard - -"@aws-sdk/middleware-stack@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-stack@npm:3.347.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/cbe170aee62d756529f05ac548968c32d8331bebe4bea22e09c0b610151a08bf3ebdb39fe839b8592c17bb0377bbbc91ea95c6953bc6b72732e30ec3ef7dbd78 - languageName: node - linkType: hard - -"@aws-sdk/middleware-user-agent@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/middleware-user-agent@npm:3.347.0" - dependencies: - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-endpoints": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/e0c7e46034de60323aba06c8a910cdae24a457ce715cfe05b675735e6795c542494134757edada67290b4c8ed63e11453dde5d11b0501d7949163f106f3647de - languageName: node - linkType: hard - -"@aws-sdk/node-config-provider@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/node-config-provider@npm:3.347.0" - dependencies: - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/shared-ini-file-loader": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/0a6fb694ad621ba3436908c4f4aefe6eac60b017019b3b9b709b6c2cc0a3da4a65787102bf70dcd4a092a4ba4900d60d13dd97fac9a1cf3dc4f2db80aba47772 - languageName: node - linkType: hard - -"@aws-sdk/node-http-handler@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/node-http-handler@npm:3.350.0" - dependencies: - "@aws-sdk/abort-controller": "npm:3.347.0" - "@aws-sdk/protocol-http": "npm:3.347.0" - "@aws-sdk/querystring-builder": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/98a6d12777dcdf67e8a20ee89af54e2cd1b9a0bfaa17bf7c818513fe9dad3cddb9dc5bdf98a1b1ab5f924c97337d690fa36bd2122d91ef160bc427f29ca57151 - languageName: node - linkType: hard - -"@aws-sdk/property-provider@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/property-provider@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/e127e0c333a179f20bbb0baaa38d7ad4e66a8b36529924ca514af947e9a559916efacba2a35856533c9d4d79793ab39b8f566753822707be308a24fb9f21d043 - languageName: node - linkType: hard - -"@aws-sdk/protocol-http@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/protocol-http@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/4b04411f2be88c46303bfc3d85250f7d73c7f4b7c6b2c8eabea98e70234491ae18901910337ad9f3901402b9b2cde24002efb91752671a8fdedb3aa782fe769b - languageName: node - linkType: hard - -"@aws-sdk/querystring-builder@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/querystring-builder@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-uri-escape": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/86c1e0352fe2b79d168a57d8ef0a0cec57ec5b3247d9e0b2f9d337fd656d77874748669bf33ee143363fd0686a5636ff1620e5cd88c5dd4aaccb904212b5a07e - languageName: node - linkType: hard - -"@aws-sdk/querystring-parser@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/querystring-parser@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/1b31b654e3397d1b8008305adf37192320658a5ccf45dc7564cc0b85769a18b4ca71d1ddd781409159bbb99a7ff99b4f79e00c0eef133669be81169b6ae73ed3 - languageName: node - linkType: hard - -"@aws-sdk/service-error-classification@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/service-error-classification@npm:3.347.0" - checksum: 10/6710a83af828bfbc81104cd11d98d7ef68ddd255a0fa1b4630b7548e9faed406bdf2c41f245aceb08107cdb6052d9ed200147f7113da28b653f3f29e87278ff9 - languageName: node - linkType: hard - -"@aws-sdk/shared-ini-file-loader@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/shared-ini-file-loader@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/a55740a6117ffdcb717f6b2629dd1df91ad055745148f03d231c4f457c4e7f9ac59de76e7b1341f804253bef542046eda4a1a44676c1690b61417e68cd6c2ad7 - languageName: node - linkType: hard - -"@aws-sdk/signature-v4@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/signature-v4@npm:3.347.0" - dependencies: - "@aws-sdk/eventstream-codec": "npm:3.347.0" - "@aws-sdk/is-array-buffer": "npm:3.310.0" - "@aws-sdk/types": "npm:3.347.0" - "@aws-sdk/util-hex-encoding": "npm:3.310.0" - "@aws-sdk/util-middleware": "npm:3.347.0" - "@aws-sdk/util-uri-escape": "npm:3.310.0" - "@aws-sdk/util-utf8": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/90e8acb577d11cf31c5738a4bb3ff488cc3447d734aa190e36bfff8f045e2a3c86e5d132cc5127f94e132bc490c41a1e7832273c801c04f9640de6fe4bbf55d1 + version: 3.817.0 + resolution: "@aws-sdk/credential-providers@npm:3.817.0" + dependencies: + "@aws-sdk/client-cognito-identity": "npm:3.817.0" + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/credential-provider-cognito-identity": "npm:3.817.0" + "@aws-sdk/credential-provider-env": "npm:3.816.0" + "@aws-sdk/credential-provider-http": "npm:3.816.0" + "@aws-sdk/credential-provider-ini": "npm:3.817.0" + "@aws-sdk/credential-provider-node": "npm:3.817.0" + "@aws-sdk/credential-provider-process": "npm:3.816.0" + "@aws-sdk/credential-provider-sso": "npm:3.817.0" + "@aws-sdk/credential-provider-web-identity": "npm:3.817.0" + "@aws-sdk/nested-clients": "npm:3.817.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/config-resolver": "npm:^4.1.2" + "@smithy/core": "npm:^3.3.3" + "@smithy/credential-provider-imds": "npm:^4.0.4" + "@smithy/node-config-provider": "npm:^4.1.1" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/deeec91aecf71cbd7a9141559053cdf6be60944fb0fe1a217811e87a03ddb7e8daa6fccf872041f47cccc9e5a7b8871853ba98848b6e734ec972d89dd50814e8 + languageName: node + linkType: hard + +"@aws-sdk/middleware-host-header@npm:3.804.0": + version: 3.804.0 + resolution: "@aws-sdk/middleware-host-header@npm:3.804.0" + dependencies: + "@aws-sdk/types": "npm:3.804.0" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/e511fc88eabf44a88458a24ad134933a01cc44704db5f9baaa179e87a541da7fee2de55ea5d1e16daedb5cad40d270d4f2fab41dd0b16db7ffa812461409194d + languageName: node + linkType: hard + +"@aws-sdk/middleware-logger@npm:3.804.0": + version: 3.804.0 + resolution: "@aws-sdk/middleware-logger@npm:3.804.0" + dependencies: + "@aws-sdk/types": "npm:3.804.0" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/18097aae48558cf5d40bda906829b500693c9a22378babd9f177886cdb88eaf3da28cf38c09952502d9f951f50821a4f9082270c77329a12e61dc4d74905ec32 + languageName: node + linkType: hard + +"@aws-sdk/middleware-recursion-detection@npm:3.804.0": + version: 3.804.0 + resolution: "@aws-sdk/middleware-recursion-detection@npm:3.804.0" + dependencies: + "@aws-sdk/types": "npm:3.804.0" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/781b4fa873a10b2b058f66eb5e5ddb758695edc62a1e802f2cba6e845e1e5e578d59e6adad4e0978020271eec5d1974b044bd529798cec1105b93ecc077ffa7d + languageName: node + linkType: hard + +"@aws-sdk/middleware-user-agent@npm:3.816.0": + version: 3.816.0 + resolution: "@aws-sdk/middleware-user-agent@npm:3.816.0" + dependencies: + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/types": "npm:3.804.0" + "@aws-sdk/util-endpoints": "npm:3.808.0" + "@smithy/core": "npm:^3.3.3" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/1b5fafbd21b1cf96309c5063472d3a91c8e202e1762bf965310da3723bc191eccc891e1d89b3602a312b051ce8221ec029d13215920dfb42502c897478da3ef9 + languageName: node + linkType: hard + +"@aws-sdk/nested-clients@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/nested-clients@npm:3.817.0" + dependencies: + "@aws-crypto/sha256-browser": "npm:5.2.0" + "@aws-crypto/sha256-js": "npm:5.2.0" + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/middleware-host-header": "npm:3.804.0" + "@aws-sdk/middleware-logger": "npm:3.804.0" + "@aws-sdk/middleware-recursion-detection": "npm:3.804.0" + "@aws-sdk/middleware-user-agent": "npm:3.816.0" + "@aws-sdk/region-config-resolver": "npm:3.808.0" + "@aws-sdk/types": "npm:3.804.0" + "@aws-sdk/util-endpoints": "npm:3.808.0" + "@aws-sdk/util-user-agent-browser": "npm:3.804.0" + "@aws-sdk/util-user-agent-node": "npm:3.816.0" + "@smithy/config-resolver": "npm:^4.1.2" + "@smithy/core": "npm:^3.3.3" + "@smithy/fetch-http-handler": "npm:^5.0.2" + "@smithy/hash-node": "npm:^4.0.2" + "@smithy/invalid-dependency": "npm:^4.0.2" + "@smithy/middleware-content-length": "npm:^4.0.2" + "@smithy/middleware-endpoint": "npm:^4.1.6" + "@smithy/middleware-retry": "npm:^4.1.7" + "@smithy/middleware-serde": "npm:^4.0.5" + "@smithy/middleware-stack": "npm:^4.0.2" + "@smithy/node-config-provider": "npm:^4.1.1" + "@smithy/node-http-handler": "npm:^4.0.4" + "@smithy/protocol-http": "npm:^5.1.0" + "@smithy/smithy-client": "npm:^4.2.6" + "@smithy/types": "npm:^4.2.0" + "@smithy/url-parser": "npm:^4.0.2" + "@smithy/util-base64": "npm:^4.0.0" + "@smithy/util-body-length-browser": "npm:^4.0.0" + "@smithy/util-body-length-node": "npm:^4.0.0" + "@smithy/util-defaults-mode-browser": "npm:^4.0.14" + "@smithy/util-defaults-mode-node": "npm:^4.0.14" + "@smithy/util-endpoints": "npm:^3.0.4" + "@smithy/util-middleware": "npm:^4.0.2" + "@smithy/util-retry": "npm:^4.0.3" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/ee798825612fd68566af155e79b200f02809f3e367c05105baec617bb06a46b958766f096b9221732f7bec53c921cef1df63c3a10868b5ea170fec7d6d53f9bf languageName: node linkType: hard -"@aws-sdk/smithy-client@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/smithy-client@npm:3.347.0" +"@aws-sdk/region-config-resolver@npm:3.808.0": + version: 3.808.0 + resolution: "@aws-sdk/region-config-resolver@npm:3.808.0" dependencies: - "@aws-sdk/middleware-stack": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/34ab9666d68e088c00e369e6451c948148850589c7d583f788a64d45d096a4a309b8ef58bc6a73d857456ce8cf773f63511e0da0c262ef25e42f0bb89afe3be8 + "@aws-sdk/types": "npm:3.804.0" + "@smithy/node-config-provider": "npm:^4.1.1" + "@smithy/types": "npm:^4.2.0" + "@smithy/util-config-provider": "npm:^4.0.0" + "@smithy/util-middleware": "npm:^4.0.2" + tslib: "npm:^2.6.2" + checksum: 10/b3710a568ba23af4169a87c497ffaebfa764f3439f3e515ec6ab4b6cd445b16901445b907fb8496a6175f86dccefbef396df23211cad5c75b899a473a8e3fda3 languageName: node linkType: hard -"@aws-sdk/token-providers@npm:3.350.0": - version: 3.350.0 - resolution: "@aws-sdk/token-providers@npm:3.350.0" - dependencies: - "@aws-sdk/client-sso-oidc": "npm:3.350.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/shared-ini-file-loader": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/b25551e16d879568375433aa1a3b7a491e590d54138f968b7ae562ae78502e088d726955ac2c60d11f03e10e74525a7d6a832124cca51f4ec6f75ee80ff6145b - languageName: node - linkType: hard - -"@aws-sdk/types@npm:3.347.0, @aws-sdk/types@npm:^3.222.0": - version: 3.347.0 - resolution: "@aws-sdk/types@npm:3.347.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/baa08033d5d1bee02c54caeb2e36fd0c23c747c9644587df439a7da072b0bb3a66f363f6ff58d1c49a5cf543df788f22e1880be936c3f551900b6c52d340766f - languageName: node - linkType: hard - -"@aws-sdk/url-parser@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/url-parser@npm:3.347.0" - dependencies: - "@aws-sdk/querystring-parser": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/d25c5bd152b842cf32042c2a1368923b8f50d10a313173cf0f3b5dfba2df8e0e47e04d9a7a78281dd415802821ceb25ccf5ce4ab7fdfe6c8f543fc669d35c1c1 - languageName: node - linkType: hard - -"@aws-sdk/util-base64@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-base64@npm:3.310.0" - dependencies: - "@aws-sdk/util-buffer-from": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/d30027c81a05bda6dcdfe82c58882b8e0f8da802a9eb3da67e0f66ab7b48e9a756c6d286a3cf77ee117375fec8c6fb7f66d9eb081bf88f348c38623321554b3a - languageName: node - linkType: hard - -"@aws-sdk/util-body-length-browser@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-body-length-browser@npm:3.310.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/a6fe0b1c95d236d1a6ee1a1b045a329dea53f12072999482677201b274201c2d06c25a55861677dd859c3f56972f3b090bef3e1c363d4a8ee33e0f276a787289 - languageName: node - linkType: hard - -"@aws-sdk/util-body-length-node@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-body-length-node@npm:3.310.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/3775cb82812c4bcf7f39bce07be5646b6a6ff720b5173aeec7cb6b004633191115920610622162639a28774d2c25fa04e768ffaa2817562c62729de5dcbda3c5 - languageName: node - linkType: hard - -"@aws-sdk/util-buffer-from@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-buffer-from@npm:3.310.0" - dependencies: - "@aws-sdk/is-array-buffer": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/bb160d9e7eae5ad1c0858c2d2e861d9fadbf6696dbea608bfafbe8bd5d55b8e5c7eca447bef954d63ef2ba5b0acaf79df9aba8d1016c2727ac0227c30d8a7ac3 - languageName: node - linkType: hard - -"@aws-sdk/util-config-provider@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-config-provider@npm:3.310.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/40d7369dc932c389efdbbf9b7c0c3a7beaee1b4082d2b63ef667e61f72e40875bd8246d1cf0e4af79d2234bf5126dd61db6fb5ebdf366becd4787140b9bcfd2d - languageName: node - linkType: hard - -"@aws-sdk/util-defaults-mode-browser@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/util-defaults-mode-browser@npm:3.347.0" - dependencies: - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - bowser: "npm:^2.11.0" - tslib: "npm:^2.5.0" - checksum: 10/ff19b25c47a691547247c5051465d1bf134c6ac428d658d58d2ad00d0470aaa7b7ad8ea52f56a6b1045b561a27f39a3e2664f14df99586cbf59088a08b9a38f2 - languageName: node - linkType: hard - -"@aws-sdk/util-defaults-mode-node@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/util-defaults-mode-node@npm:3.347.0" - dependencies: - "@aws-sdk/config-resolver": "npm:3.347.0" - "@aws-sdk/credential-provider-imds": "npm:3.347.0" - "@aws-sdk/node-config-provider": "npm:3.347.0" - "@aws-sdk/property-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/20d9eaea6dc36d102cc82b233f857b865347112f5e7e47e6daa47cfc3d4f3feafb045381143a07ff88fa992ddfd2620f628cb44e4b04146aca07f2f08b934bed - languageName: node - linkType: hard - -"@aws-sdk/util-endpoints@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/util-endpoints@npm:3.347.0" - dependencies: - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/f643fa4fb332d4fc77232aa00d222a760e8b592d1b597ec339515226559fb6b45f8a5c6084bf3fe075349bbd0c060b563569b6d6749660a85014685fde2657bf - languageName: node - linkType: hard - -"@aws-sdk/util-hex-encoding@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-hex-encoding@npm:3.310.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/9ec0388c9667d4d616c61530be88422a315e3d92bf93b941d6f6d8339d6e703f4cacb2e11402658d716b1166e90d0fddb497284220e11075a0c17821c468c44b +"@aws-sdk/token-providers@npm:3.817.0": + version: 3.817.0 + resolution: "@aws-sdk/token-providers@npm:3.817.0" + dependencies: + "@aws-sdk/core": "npm:3.816.0" + "@aws-sdk/nested-clients": "npm:3.817.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/property-provider": "npm:^4.0.2" + "@smithy/shared-ini-file-loader": "npm:^4.0.2" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/f28319417ac3b94a8340d35672b6e75d421c7dc837d5dfb45a1e06ad94f5d6b2cf4b0b7639b7f2869dcf9a94c7a5d7ecfe23f7cd02efa81ef6fa99a8e30845c2 + languageName: node + linkType: hard + +"@aws-sdk/types@npm:3.804.0, @aws-sdk/types@npm:^3.222.0": + version: 3.804.0 + resolution: "@aws-sdk/types@npm:3.804.0" + dependencies: + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" + checksum: 10/832be8774a2322f2114c93a632876308edd94b4def2005facade754e0ada38a96dab0919444387440ae94f5b562c6b8195b93a70c401c3fa6541f1980224739d + languageName: node + linkType: hard + +"@aws-sdk/util-endpoints@npm:3.808.0": + version: 3.808.0 + resolution: "@aws-sdk/util-endpoints@npm:3.808.0" + dependencies: + "@aws-sdk/types": "npm:3.804.0" + "@smithy/types": "npm:^4.2.0" + "@smithy/util-endpoints": "npm:^3.0.4" + tslib: "npm:^2.6.2" + checksum: 10/bc735ac0d7c58d12e5ef820050879bba7300534ff9e05a3f0c3cb32ac5874e208b7e000e5cb4d04f407789cef0e48926e1564a5edc89f64a141b3494970f6ba4 languageName: node linkType: hard "@aws-sdk/util-locate-window@npm:^3.0.0": - version: 3.310.0 - resolution: "@aws-sdk/util-locate-window@npm:3.310.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/163f27aad377c3f798b814bea57bfe1388fbc8a8411407e4c0c23328e32d171645645ac3f4c72e14bf2430a4794b5a5966d9b40c675256b23fa6299a2eb976aa - languageName: node - linkType: hard - -"@aws-sdk/util-middleware@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/util-middleware@npm:3.347.0" - dependencies: - tslib: "npm:^2.5.0" - checksum: 10/2cb72f33427d5c9ee0157b176c472676c9b6ed9c03c4f21743ab93a5a01ed4b4b755d8f798d2d999a63f64d5bcb94a188b0095f6928316e9eb7026877c23b08e - languageName: node - linkType: hard - -"@aws-sdk/util-retry@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/util-retry@npm:3.347.0" - dependencies: - "@aws-sdk/service-error-classification": "npm:3.347.0" - tslib: "npm:^2.5.0" - checksum: 10/551ef97c33d060781e3ee38d507065720c1714fc826f74561bbc47b0bb00d3de4ba0a837de41b09b740b216a6ad641f500d8cd9e935a8074ef6af689ca55f64a - languageName: node - linkType: hard - -"@aws-sdk/util-uri-escape@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-uri-escape@npm:3.310.0" + version: 3.804.0 + resolution: "@aws-sdk/util-locate-window@npm:3.804.0" dependencies: - tslib: "npm:^2.5.0" - checksum: 10/04ca4f2ee9226236d6c629a58329312c5c316b2a0bf29c55f63075447de039c041144755e42ca11db2fd79a793d82bd9e548e7ba5b3ef6b41db5f66aac769e23 + tslib: "npm:^2.6.2" + checksum: 10/4f1ad094cf9f23a6f09dbad8823d3c58d628412352a045e2fb3bea66281aa59a944545ffd8ed09b096b60b44671fb3fd3f3bfb5b924f3326ee82fb68c2c7b785 languageName: node linkType: hard -"@aws-sdk/util-user-agent-browser@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/util-user-agent-browser@npm:3.347.0" +"@aws-sdk/util-user-agent-browser@npm:3.804.0": + version: 3.804.0 + resolution: "@aws-sdk/util-user-agent-browser@npm:3.804.0" dependencies: - "@aws-sdk/types": "npm:3.347.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/types": "npm:^4.2.0" bowser: "npm:^2.11.0" - tslib: "npm:^2.5.0" - checksum: 10/9fa6a9f680eeb5807c462953511dd0826101aedc6097f79180131bb2aecfcc81158e911864d75cbc5a163fac3a7ad0796f2fbfe2410c6e0deed8cb41e33fab4d + tslib: "npm:^2.6.2" + checksum: 10/6fe62a4625acc86cc018e6646b6737eec1aface0f0ae8215431eef740635cf3d2339e859f77d4030db696ac36a69a309fe2d2534b45e790feeb596f39c83e135 languageName: node linkType: hard -"@aws-sdk/util-user-agent-node@npm:3.347.0": - version: 3.347.0 - resolution: "@aws-sdk/util-user-agent-node@npm:3.347.0" +"@aws-sdk/util-user-agent-node@npm:3.816.0": + version: 3.816.0 + resolution: "@aws-sdk/util-user-agent-node@npm:3.816.0" dependencies: - "@aws-sdk/node-config-provider": "npm:3.347.0" - "@aws-sdk/types": "npm:3.347.0" - tslib: "npm:^2.5.0" + "@aws-sdk/middleware-user-agent": "npm:3.816.0" + "@aws-sdk/types": "npm:3.804.0" + "@smithy/node-config-provider": "npm:^4.1.1" + "@smithy/types": "npm:^4.2.0" + tslib: "npm:^2.6.2" peerDependencies: aws-crt: ">=1.0.0" peerDependenciesMeta: aws-crt: optional: true - checksum: 10/1afd13c459e047b5a7dbd0082c51be276b20d20105ceaa16c625512c416e9bf0abcef99b3c39b3cf14396680fdcd0f03f119bcd2c9d36171aa7cf92c14ec43ea - languageName: node - linkType: hard - -"@aws-sdk/util-utf8-browser@npm:^3.0.0": - version: 3.259.0 - resolution: "@aws-sdk/util-utf8-browser@npm:3.259.0" - dependencies: - tslib: "npm:^2.3.1" - checksum: 10/bdcf29a92a9a1010b44bf8bade3f1224cb6577a6550b39df97cc053d353f2868d355c25589d61e1da54691d65350d8578a496840ad770ed916a6c3af0971f657 - languageName: node - linkType: hard - -"@aws-sdk/util-utf8@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-utf8@npm:3.310.0" - dependencies: - "@aws-sdk/util-buffer-from": "npm:3.310.0" - tslib: "npm:^2.5.0" - checksum: 10/88bf031527a1fe99712b4e2cb00bc47436b39aa29ce0ceeace3bd0bc7d436d14940f190c249b9a69e684f8d3f01f96847848f5d8ebab7e3103c0084c1e609ce4 + checksum: 10/96ac27c29054912103420c6d2b5997d04f60ec135ee3b4c26ce09a241cbba1de74a39217278186be91e44ab936f0a2b302644d2365265a8b53669b3599dc289e languageName: node linkType: hard -"@babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.1": - version: 7.24.2 - resolution: "@babel/code-frame@npm:7.24.2" +"@babel/code-frame@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/code-frame@npm:7.27.1" dependencies: - "@babel/highlight": "npm:^7.24.2" - picocolors: "npm:^1.0.0" - checksum: 10/7db8f5b36ffa3f47a37f58f61e3d130b9ecad21961f3eede7e2a4ac2c7e4a5efb6e9d03a810c669bc986096831b6c0dfc2c3082673d93351b82359c1b03e0590 + "@babel/helper-validator-identifier": "npm:^7.27.1" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10/721b8a6e360a1fa0f1c9fe7351ae6c874828e119183688b533c477aa378f1010f37cc9afbfc4722c686d1f5cdd00da02eab4ba7278a0c504fa0d7a321dcd4fdf languageName: node linkType: hard -"@babel/compat-data@npm:^7.23.5": - version: 7.24.1 - resolution: "@babel/compat-data@npm:7.24.1" - checksum: 10/d5460b99c07ff8487467c52f742a219c7e3bcdcaa2882456a13c0d0c8116405f0c85a651fb60511284dc64ed627a5e989f24c3cd6e71d07a9947e7c8954b433c +"@babel/compat-data@npm:^7.27.2": + version: 7.27.2 + resolution: "@babel/compat-data@npm:7.27.2" + checksum: 10/eaa9f8aaeb9475779f4411fa397f712a6441b650d4e0b40c5535c954c891cd35c0363004db42902192aa8224532ac31ce06890478b060995286fe4fadd54e542 languageName: node linkType: hard -"@babel/core@npm:^7.23.5": - version: 7.24.1 - resolution: "@babel/core@npm:7.24.1" +"@babel/core@npm:^7.26.10": + version: 7.27.1 + resolution: "@babel/core@npm:7.27.1" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.24.1" - "@babel/generator": "npm:^7.24.1" - "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.24.1" - "@babel/parser": "npm:^7.24.1" - "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.1" - "@babel/types": "npm:^7.24.0" + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.27.1" + "@babel/helper-compilation-targets": "npm:^7.27.1" + "@babel/helper-module-transforms": "npm:^7.27.1" + "@babel/helpers": "npm:^7.27.1" + "@babel/parser": "npm:^7.27.1" + "@babel/template": "npm:^7.27.1" + "@babel/traverse": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10/f8c153acd619a5d17caee7aff052a2aa306ceda280ffc07182d7b5dd40c41c7511ae89d64bc23ec5555e4639fc9c87ceb7b4afc12252acab548ebb7654397680 + checksum: 10/3dfec88f84b3ce567e6c482db0119f02f451bd3f86b0835c71c029fedb657969786507fafedd3a0732bd1be9fbc9f0635d734efafabad6dbc67d3eb7b494cdd8 languageName: node linkType: hard -"@babel/generator@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/generator@npm:7.24.1" +"@babel/generator@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/generator@npm:7.27.1" dependencies: - "@babel/types": "npm:^7.24.0" + "@babel/parser": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" - jsesc: "npm:^2.5.1" - checksum: 10/c6160e9cd63d7ed7168dee27d827f9c46fab820c45861a5df56cd5c78047f7c3fc97c341e9ccfa1a6f97c87ec2563d9903380b5f92794e3540a6c5f99eb8f075 + jsesc: "npm:^3.0.2" + checksum: 10/6101825922a8a116e64b507d9309b38c5bc027b333d7111fcb760422741d3c72bd8f8e5aa935c2944c434ffe376353a27afa3a25a8526dc2ef90743d266770db languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/helper-compilation-targets@npm:7.23.6" +"@babel/helper-compilation-targets@npm:^7.27.1": + version: 7.27.2 + resolution: "@babel/helper-compilation-targets@npm:7.27.2" dependencies: - "@babel/compat-data": "npm:^7.23.5" - "@babel/helper-validator-option": "npm:^7.23.5" - browserslist: "npm:^4.22.2" + "@babel/compat-data": "npm:^7.27.2" + "@babel/helper-validator-option": "npm:^7.27.1" + browserslist: "npm:^4.24.0" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10/05595cd73087ddcd81b82d2f3297aac0c0422858dfdded43d304786cf680ec33e846e2317e6992d2c964ee61d93945cbf1fa8ec80b55aee5bfb159227fb02cb9 - languageName: node - linkType: hard - -"@babel/helper-environment-visitor@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-environment-visitor@npm:7.22.20" - checksum: 10/d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-function-name@npm:7.23.0" - dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/types": "npm:^7.23.0" - checksum: 10/7b2ae024cd7a09f19817daf99e0153b3bf2bc4ab344e197e8d13623d5e36117ed0b110914bc248faa64e8ccd3e97971ec7b41cc6fd6163a2b980220c58dcdf6d - languageName: node - linkType: hard - -"@babel/helper-hoist-variables@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-hoist-variables@npm:7.22.5" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc + checksum: 10/bd53c30a7477049db04b655d11f4c3500aea3bcbc2497cf02161de2ecf994fec7c098aabbcebe210ffabc2ecbdb1e3ffad23fb4d3f18723b814f423ea1749fe8 languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.22.15": - version: 7.24.1 - resolution: "@babel/helper-module-imports@npm:7.24.1" +"@babel/helper-module-imports@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-module-imports@npm:7.27.1" dependencies: - "@babel/types": "npm:^7.24.0" - checksum: 10/f771c1e8776890d85c2af06a6a36410cb41ff4bbcf162e7eecce7d53ebdc5196cc38c3abea3a06df9d778bb20edccb2909dfb8187ae82730e4d021329b631921 + "@babel/traverse": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" + checksum: 10/58e792ea5d4ae71676e0d03d9fef33e886a09602addc3bd01388a98d87df9fcfd192968feb40ac4aedb7e287ec3d0c17b33e3ecefe002592041a91d8a1998a8d languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/helper-module-transforms@npm:7.23.3" +"@babel/helper-module-transforms@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-module-transforms@npm:7.27.1" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-module-imports": "npm:^7.22.15" - "@babel/helper-simple-access": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + "@babel/traverse": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10/583fa580f8e50e6f45c4f46aa76a8e49c2528deb84e25f634d66461b9a0e2420e13979b0a607b67aef67eaf8db8668eb9edc038b4514b16e3879fe09e8fd294b - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.24.0": - version: 7.24.0 - resolution: "@babel/helper-plugin-utils@npm:7.24.0" - checksum: 10/dc8c7af321baf7653d93315beffee1790eb2c464b4f529273a24c8743a3f3095bf3f2d11828cb2c52d56282ef43a4bdc67a79c9ab8dd845e35d01871f3f28a0e - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-simple-access@npm:7.22.5" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/7d5430eecf880937c27d1aed14245003bd1c7383ae07d652b3932f450f60bfcf8f2c1270c593ab063add185108d26198c69d1aca0e6fb7c6fdada4bcf72ab5b7 + checksum: 10/415509a5854203073755aab3ad293664146a55777355b5b5187902f976162c9565907d2276f7f6e778527be4829db2d926015d446100a65f2538d6397d83e248 languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/helper-split-export-declaration@npm:7.22.6" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 +"@babel/helper-plugin-utils@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-plugin-utils@npm:7.27.1" + checksum: 10/96136c2428888e620e2ec493c25888f9ceb4a21099dcf3dd4508ea64b58cdedbd5a9fb6c7b352546de84d6c24edafe482318646932a22c449ebd16d16c22d864 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.23.4": - version: 7.24.1 - resolution: "@babel/helper-string-parser@npm:7.24.1" - checksum: 10/04c0ede77b908b43e6124753b48bc485528112a9335f0a21a226bff1ace75bb6e64fab24c85cb4b1610ef3494dacd1cb807caeb6b79a7b36c43d48c289b35949 +"@babel/helper-string-parser@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-string-parser@npm:7.27.1" + checksum: 10/0ae29cc2005084abdae2966afdb86ed14d41c9c37db02c3693d5022fba9f5d59b011d039380b8e537c34daf117c549f52b452398f576e908fb9db3c7abbb3a00 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: 10/df882d2675101df2d507b95b195ca2f86a3ef28cb711c84f37e79ca23178e13b9f0d8b522774211f51e40168bf5142be4c1c9776a150cddb61a0d5bf3e95750b +"@babel/helper-validator-identifier@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-identifier@npm:7.27.1" + checksum: 10/75041904d21bdc0cd3b07a8ac90b11d64cd3c881e89cb936fa80edd734bf23c35e6bd1312611e8574c4eab1f3af0f63e8a5894f4699e9cfdf70c06fcf4252320 languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/helper-validator-option@npm:7.23.5" - checksum: 10/537cde2330a8aede223552510e8a13e9c1c8798afee3757995a7d4acae564124fe2bf7e7c3d90d62d3657434a74340a274b3b3b1c6f17e9a2be1f48af29cb09e +"@babel/helper-validator-option@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-option@npm:7.27.1" + checksum: 10/db73e6a308092531c629ee5de7f0d04390835b21a263be2644276cb27da2384b64676cab9f22cd8d8dbd854c92b1d7d56fc8517cf0070c35d1c14a8c828b0903 languageName: node linkType: hard -"@babel/helpers@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/helpers@npm:7.24.1" +"@babel/helpers@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helpers@npm:7.27.1" dependencies: - "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.1" - "@babel/types": "npm:^7.24.0" - checksum: 10/82d3cdd3beafc4583f237515ef220bc205ced8b0540c6c6e191fc367a9589bd7304b8f9800d3d7574d4db9f079bd555979816b1874c86e53b3e7dd2032ad6c7c + "@babel/template": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" + checksum: 10/b86ee2c87d52640c63ec1fdf139d4560efc173ae6379659e0df49a3c0cf1d5f24436132ebb4459a4ee72418b43b39ee001f4e01465b48c8d31911a745ec4fd74 languageName: node linkType: hard -"@babel/highlight@npm:^7.24.2": - version: 7.24.2 - resolution: "@babel/highlight@npm:7.24.2" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.27.1, @babel/parser@npm:^7.27.2": + version: 7.27.2 + resolution: "@babel/parser@npm:7.27.2" dependencies: - "@babel/helper-validator-identifier": "npm:^7.22.20" - chalk: "npm:^2.4.2" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.0.0" - checksum: 10/4555124235f34403bb28f55b1de58edf598491cc181c75f8afc8fe529903cb598cd52fe3bf2faab9bc1f45c299681ef0e44eea7a848bb85c500c5a4fe13f54f6 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/parser@npm:7.24.1" + "@babel/types": "npm:^7.27.1" bin: parser: ./bin/babel-parser.js - checksum: 10/561d9454091e07ecfec3828ce79204c0fc9d24e17763f36181c6984392be4ca6b79c8225f2224fdb7b1b3b70940e243368c8f83ac77ec2dc20f46d3d06bd6795 + checksum: 10/133b4ccfbc01d4f36b0945937aabff87026c29fda6dcd3c842053a672e50f2487a101a3acd150bbaa2eecd33f3bd35650f95b806567c926f93b2af35c2b615c9 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-self@npm:^7.23.3": - version: 7.24.1 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.24.1" +"@babel/plugin-transform-react-jsx-self@npm:^7.25.9": + version: 7.27.1 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.27.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/a0ff893b946bb0e501ad5aab43ce4b321ed9e74b94c0bc7191e2ee6409014fc96ee1a47dcb1ecdf445c44868564667ae16507ed4516dcacf6aa9c37a0ad28382 + checksum: 10/72cbae66a58c6c36f7e12e8ed79f292192d858dd4bb00e9e89d8b695e4c5cb6ef48eec84bffff421a5db93fd10412c581f1cccdb00264065df76f121995bdb68 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-source@npm:^7.23.3": - version: 7.24.1 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.24.1" +"@babel/plugin-transform-react-jsx-source@npm:^7.25.9": + version: 7.27.1 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.27.1" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10/396ce878dc588e74113d38c5a1773e0850bb878a073238a74f8cdf62d968d56a644f5485bf4032dc095fe8863fe2bd9fbbbab6abc3adf69542e038ac5c689d4c + checksum: 10/e2843362adb53692be5ee9fa07a386d2d8883daad2063a3575b3c373fc14cdf4ea7978c67a183cb631b4c9c8d77b2f48c24c088f8e65cc3600cb8e97d72a7161 languageName: node linkType: hard -"@babel/template@npm:^7.22.15, @babel/template@npm:^7.24.0": - version: 7.24.0 - resolution: "@babel/template@npm:7.24.0" +"@babel/template@npm:^7.27.1": + version: 7.27.2 + resolution: "@babel/template@npm:7.27.2" dependencies: - "@babel/code-frame": "npm:^7.23.5" - "@babel/parser": "npm:^7.24.0" - "@babel/types": "npm:^7.24.0" - checksum: 10/8c538338c7de8fac8ada691a5a812bdcbd60bd4a4eb5adae2cc9ee19773e8fb1a724312a00af9e1ce49056ffd3c3475e7287b5668cf6360bfb3f8ac827a06ffe + "@babel/code-frame": "npm:^7.27.1" + "@babel/parser": "npm:^7.27.2" + "@babel/types": "npm:^7.27.1" + checksum: 10/fed15a84beb0b9340e5f81566600dbee5eccd92e4b9cc42a944359b1aa1082373391d9d5fc3656981dff27233ec935d0bc96453cf507f60a4b079463999244d8 languageName: node linkType: hard -"@babel/traverse@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/traverse@npm:7.24.1" +"@babel/traverse@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/traverse@npm:7.27.1" dependencies: - "@babel/code-frame": "npm:^7.24.1" - "@babel/generator": "npm:^7.24.1" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.24.1" - "@babel/types": "npm:^7.24.0" + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.27.1" + "@babel/parser": "npm:^7.27.1" + "@babel/template": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10/b9b0173c286ef549e179f3725df3c4958069ad79fe5b9840adeb99692eb4a5a08db4e735c0f086aab52e7e08ec711cee9e7c06cb908d8035641d1382172308d3 + checksum: 10/9977271aa451293d3f184521412788d6ddaff9d6a29626d7435b5dacd059feb2d7753bc94f59f4f5b76e65bd2e2cabc8a10d7e1f93709feda28619f2e8cbf4d6 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.24.0, @babel/types@npm:^7.8.3": - version: 7.24.0 - resolution: "@babel/types@npm:7.24.0" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/types@npm:7.27.1" dependencies: - "@babel/helper-string-parser": "npm:^7.23.4" - "@babel/helper-validator-identifier": "npm:^7.22.20" - to-fast-properties: "npm:^2.0.0" - checksum: 10/a0b4875ce2e132f9daff0d5b27c7f4c4fcc97f2b084bdc5834e92c9d32592778489029e65d99d00c406da612d87b72d7a236c0afccaa1435c028d0c94c9b6da4 + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + checksum: 10/81f8ada28c4b29695d7d4c4cbfaa5ec3138ccebbeb26628c7c3cc570fdc84f28967c9e68caf4977d51ff4f4d3159c88857ef278317f84f3515dd65e5b8a74995 languageName: node linkType: hard @@ -1249,6 +800,7 @@ __metadata: dependencies: "@craft/engine": "npm:1.0.0" "@craft/eslint-config-tylercraft": "npm:^1.0.0" + "@tailwindcss/vite": "npm:^4.1.7" "@types/gl-matrix": "npm:^2.4.5" "@types/react": "npm:^18.2.67" "@types/react-dom": "npm:^18" @@ -1258,6 +810,8 @@ __metadata: gl-matrix: "npm:2.4.0" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" + react-router-dom: "npm:^6.8.0" + tailwindcss: "npm:^4.1.7" typescript: "npm:^5.5.3" vite: "npm:^5.1.6" vite-plugin-top-level-await: "npm:^1.4.1" @@ -1265,224 +819,245 @@ __metadata: languageName: unknown linkType: soft -"@esbuild/aix-ppc64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/aix-ppc64@npm:0.19.12" +"@emnapi/core@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/core@npm:1.4.3" + dependencies: + "@emnapi/wasi-threads": "npm:1.0.2" + tslib: "npm:^2.4.0" + checksum: 10/b511f66b897d2019835391544fdf11f4fa0ce06cc1181abfa17c7d4cf03aaaa4fc8a64fcd30bb3f901de488d0a6f370b53a8de2215a898f5a4ac98015265b3b7 + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/runtime@npm:1.4.3" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/4f90852a1a5912982cc4e176b6420556971bcf6a85ee23e379e2455066d616219751367dcf43e6a6eaf41ea7e95ba9dc830665a52b5d979dfe074237d19578f8 + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.0.2, @emnapi/wasi-threads@npm:^1.0.2": + version: 1.0.2 + resolution: "@emnapi/wasi-threads@npm:1.0.2" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/e82941776665eb958c2084728191d6b15a94383449975c4621b67a1c8217e1c0ec11056a693906c76863cb96f782f8be500510ecec6874e3f5da35a8e7968cfd + languageName: node + linkType: hard + +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/android-arm64@npm:0.19.12" +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/android-arm@npm:0.19.12" +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/android-x64@npm:0.19.12" +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/darwin-arm64@npm:0.19.12" +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/darwin-x64@npm:0.19.12" +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/freebsd-arm64@npm:0.19.12" +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/freebsd-x64@npm:0.19.12" +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-arm64@npm:0.19.12" +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-arm@npm:0.19.12" +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-ia32@npm:0.19.12" +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-loong64@npm:0.19.12" +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-mips64el@npm:0.19.12" +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-ppc64@npm:0.19.12" +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-riscv64@npm:0.19.12" +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-s390x@npm:0.19.12" +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/linux-x64@npm:0.19.12" +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/netbsd-x64@npm:0.19.12" +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/openbsd-x64@npm:0.19.12" +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/sunos-x64@npm:0.19.12" +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/win32-arm64@npm:0.19.12" +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/win32-ia32@npm:0.19.12" +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.19.12": - version: 0.19.12 - resolution: "@esbuild/win32-x64@npm:0.19.12" +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@eslint-community/eslint-utils@npm:^4.2.0": - version: 4.4.0 - resolution: "@eslint-community/eslint-utils@npm:4.4.0" + version: 4.7.0 + resolution: "@eslint-community/eslint-utils@npm:4.7.0" dependencies: - eslint-visitor-keys: "npm:^3.3.0" + eslint-visitor-keys: "npm:^3.4.3" peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10/8d70bcdcd8cd279049183aca747d6c2ed7092a5cf0cf5916faac1ef37ffa74f0c245c2a3a3d3b9979d9dfdd4ca59257b4c5621db699d637b847a2c5e02f491c2 + checksum: 10/43ed5d391526d9f5bbe452aef336389a473026fca92057cf97c576db11401ce9bcf8ef0bf72625bbaf6207ed8ba6bf0dcf4d7e809c24f08faa68a28533c491a7 languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.4.0": - version: 4.5.1 - resolution: "@eslint-community/regexpp@npm:4.5.1" - checksum: 10/e31e456d44e9bf98d59c8ac445549098e1a6d9c4e22053cad58e86a9f78a1e64104ef7f7f46255c442e0c878fe0e566ffba287787d070196c83510ef30d1d197 +"@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.6.1": + version: 4.12.1 + resolution: "@eslint-community/regexpp@npm:4.12.1" + checksum: 10/c08f1dd7dd18fbb60bdd0d85820656d1374dd898af9be7f82cb00451313402a22d5e30569c150315b4385907cdbca78c22389b2a72ab78883b3173be317620cc languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.0.3": - version: 2.0.3 - resolution: "@eslint/eslintrc@npm:2.0.3" +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" - espree: "npm:^9.5.2" + espree: "npm:^9.6.0" globals: "npm:^13.19.0" ignore: "npm:^5.2.0" import-fresh: "npm:^3.2.1" js-yaml: "npm:^4.1.0" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: 10/3508a9eb1a1cdf205f34648a993862b15c178669b71d6a9544787558b925ac689d8ddf3e598990156a17b708e79d3cb867fb45d5662908d14c1b10eaad858516 - languageName: node - linkType: hard - -"@eslint/js@npm:8.42.0": - version: 8.42.0 - resolution: "@eslint/js@npm:8.42.0" - checksum: 10/f6efef5c8071c997e68d6d83dd67e1de51b68932c61e9d9db10166d01c589c4d4b4dbf1ba10f6eb6f4381a790dc3036d0843f2f2c15635423af88d4a37f3117e + checksum: 10/7a3b14f4b40fc1a22624c3f84d9f467a3d9ea1ca6e9a372116cb92507e485260359465b58e25bcb6c9981b155416b98c9973ad9b796053fd7b3f776a6946bce8 languageName: node linkType: hard -"@gar/promisify@npm:^1.1.3": - version: 1.1.3 - resolution: "@gar/promisify@npm:1.1.3" - checksum: 10/052dd232140fa60e81588000cbe729a40146579b361f1070bce63e2a761388a22a16d00beeffc504bd3601cb8e055c57b21a185448b3ed550cf50716f4fd442e +"@eslint/js@npm:8.57.1": + version: 8.57.1 + resolution: "@eslint/js@npm:8.57.1" + checksum: 10/7562b21be10c2adbfa4aa5bb2eccec2cb9ac649a3569560742202c8d1cb6c931ce634937a2f0f551e078403a1c1285d6c2c0aa345dafc986149665cd69fe8b59 languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.10": - version: 0.11.10 - resolution: "@humanwhocodes/config-array@npm:0.11.10" +"@humanwhocodes/config-array@npm:^0.13.0": + version: 0.13.0 + resolution: "@humanwhocodes/config-array@npm:0.13.0" dependencies: - "@humanwhocodes/object-schema": "npm:^1.2.1" - debug: "npm:^4.1.1" + "@humanwhocodes/object-schema": "npm:^2.0.3" + debug: "npm:^4.3.1" minimatch: "npm:^3.0.5" - checksum: 10/f93086ae6a340e739a6bb23d4575b69f52acc4e4e3d62968eaaf77a77db4ba69d6d3e50c0028ba19b634ef6b241553a9d9a13d91b797b3ea33d5d711bb3362fb + checksum: 10/524df31e61a85392a2433bf5d03164e03da26c03d009f27852e7dcfdafbc4a23f17f021dacf88e0a7a9fe04ca032017945d19b57a16e2676d9114c22a53a9d11 languageName: node linkType: hard @@ -1493,21 +1068,44 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^1.2.1": - version: 1.2.1 - resolution: "@humanwhocodes/object-schema@npm:1.2.1" - checksum: 10/b48a8f87fcd5fdc4ac60a31a8bf710d19cc64556050575e6a35a4a48a8543cf8cde1598a65640ff2cdfbfd165b38f9db4fa3782bea7848eb585cc3db824002e6 +"@humanwhocodes/object-schema@npm:^2.0.3": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: 10/05bb99ed06c16408a45a833f03a732f59bf6184795d4efadd33238ff8699190a8c871ad1121241bb6501589a9598dc83bf25b99dcbcf41e155cdf36e35e937a3 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 10/e9ed5fd27c3aec1095e3a16e0c0cf148d1fee55a38665c35f7b3f86a9b5d00d042ddaabc98e8a1cb7463b9378c15f22a94eb35e99469c201453eb8375191f243 + languageName: node + linkType: hard + +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10/4412e9e6713c89c1e66d80bb0bb5a2a93192f10477623a27d08f228ba0316bb880affabc5bfe7f838f58a34d26c2c190da726e576cdfc18c49a72e89adabdcf5 languageName: node linkType: hard "@jridgewell/gen-mapping@npm:^0.3.5": - version: 0.3.5 - resolution: "@jridgewell/gen-mapping@npm:0.3.5" + version: 0.3.8 + resolution: "@jridgewell/gen-mapping@npm:0.3.8" dependencies: "@jridgewell/set-array": "npm:^1.2.1" "@jridgewell/sourcemap-codec": "npm:^1.4.10" "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10/81587b3c4dd8e6c60252122937cea0c637486311f4ed208b52b62aae2e7a87598f63ec330e6cd0984af494bfb16d3f0d60d3b21d7e5b4aedd2602ff3fe9d32e2 + checksum: 10/9d3a56ab3612ab9b85d38b2a93b87f3324f11c5130859957f6500e4ac8ce35f299d5ccc3ecd1ae87597601ecf83cee29e9afd04c18777c24011073992ff946df languageName: node linkType: hard @@ -1525,10 +1123,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: 10/89960ac087781b961ad918978975bcdf2051cd1741880469783c42de64239703eab9db5230d776d8e6a09d73bb5e4cb964e07d93ee6e2e7aea5a7d726e865c09 +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 10/4ed6123217569a1484419ac53f6ea0d9f3b57e5b57ab30d7c267bdb27792a27eb0e4b08e84a2680aa55cc2f2b411ffd6ec3db01c44fdc6dc43aca4b55f8374fd languageName: node linkType: hard @@ -1542,13 +1140,23 @@ __metadata: languageName: node linkType: hard -"@nodelib/fs.scandir@npm:2.1.3": - version: 2.1.3 - resolution: "@nodelib/fs.scandir@npm:2.1.3" +"@mongodb-js/saslprep@npm:^1.1.0, @mongodb-js/saslprep@npm:^1.1.9": + version: 1.2.2 + resolution: "@mongodb-js/saslprep@npm:1.2.2" dependencies: - "@nodelib/fs.stat": "npm:2.0.3" - run-parallel: "npm:^1.1.9" - checksum: 10/7a37ebcfadf6fd5c1aafefd7f6759d341be42cb7e1dd53455d0bfc2f730e2449bd71ba299b38ca0200f16af1bdf3ebc45bcb2972bf91df17e49acf433537bc8e + sparse-bitfield: "npm:^3.0.3" + checksum: 10/f62b2ffc072c0df0fe7d60c8159fb67dcb8ce8d8ad5ba72a09dac432acaf548c8d978a20fc2ec15cff06920029eb75ed3ad368f699e65b83f929fb4dd9b9b2f8 + languageName: node + linkType: hard + +"@napi-rs/wasm-runtime@npm:^0.2.9": + version: 0.2.10 + resolution: "@napi-rs/wasm-runtime@npm:0.2.10" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.9.0" + checksum: 10/1e4cf77891390825b1756eb5e302035b80c9dd21959417c4e4ed063eacfb6df9f42dfc001bf0fa9c9dbd0a7374342502feaa0a59103e7ea9aa5b318732280a49 languageName: node linkType: hard @@ -1562,318 +1170,1000 @@ __metadata: languageName: node linkType: hard -"@nodelib/fs.stat@npm:2.0.3, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.3 - resolution: "@nodelib/fs.stat@npm:2.0.3" - checksum: 10/c883a168a7bf1931f6818fa23691c7ed0f9129149f91a0926a86a7aee4f0febc9df479d898ef2b2a6de5533824ede506cfbec076e8fa17bfd82c76d2001cd4a0 - languageName: node - linkType: hard - -"@nodelib/fs.stat@npm:2.0.5": +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": version: 2.0.5 resolution: "@nodelib/fs.stat@npm:2.0.5" checksum: 10/012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 languageName: node linkType: hard -"@nodelib/fs.walk@npm:^1.2.3": - version: 1.2.4 - resolution: "@nodelib/fs.walk@npm:1.2.4" +"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": "npm:2.1.5" + fastq: "npm:^1.6.0" + checksum: 10/40033e33e96e97d77fba5a238e4bba4487b8284678906a9f616b5579ddaf868a18874c0054a75402c9fbaaa033a25ceae093af58c9c30278e35c23c9479e79b0 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10/775c9a7eb1f88c195dfb3bce70c31d0fe2a12b28b754e25c08a3edb4bc4816bfedb7ac64ef1e730579d078ca19dacf11630e99f8f3c3e0fd7b23caa5fd6d30a6 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10/405c4490e1ff11cf299775449a3c254a366a4b1ffc79d87159b0ee7d5558ac9f6a2f8c0735fd6ff3873cef014cb1a44a5f9127cb6a1b2dbc408718cca9365b5a + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 10/115e8ceeec6bc69dff2048b35c0ab4f8bbee12d8bb6c1f4af758604586d802b6e669dcb02dda61d078de42c2b4ddce41b3d9e726d7daa6b4b850f4adbf7333ff + languageName: node + linkType: hard + +"@remix-run/router@npm:1.23.0": + version: 1.23.0 + resolution: "@remix-run/router@npm:1.23.0" + checksum: 10/0a9f02c26c150d8210b05927c43d2f57ee8b7f812c81abb76df1721c7367ef692e54f4044981e756ce13d0619fb3c6a9b1514524d69aea9b32bfaf565299a8c7 + languageName: node + linkType: hard + +"@rolldown/pluginutils@npm:1.0.0-beta.9": + version: 1.0.0-beta.9 + resolution: "@rolldown/pluginutils@npm:1.0.0-beta.9" + checksum: 10/6d28647e1c186b0e31e07666b850a609efcf5cd5fb0ab57730f932bf57dd2ff9dec15407422e2207503463cbe2fdb4759aaf735f27cb3bbdcca6a083e78a32c0 + languageName: node + linkType: hard + +"@rollup/plugin-virtual@npm:^3.0.2": + version: 3.0.2 + resolution: "@rollup/plugin-virtual@npm:3.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10/962bc9efece57a07c328a3d093bd1a62b9b4396a88640ac79cfc04181e06b31c4b37726ca27ded71178ace27db9b0085b43c4de823378773bb44cb233ea1340e + languageName: node + linkType: hard + +"@rollup/rollup-android-arm-eabi@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.41.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-android-arm64@npm:4.41.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.41.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.41.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-arm64@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.41.1" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-x64@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-freebsd-x64@npm:4.41.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.41.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.41.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.41.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.41.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-loongarch64-gnu@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.41.1" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.41.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.41.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-musl@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.41.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.41.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.41.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.41.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.41.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.41.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.41.1": + version: 4.41.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.41.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@smithy/abort-controller@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/abort-controller@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/254721823c9f7f65a5db53542c3559eac3038e2aa3f3579791f673fa92d7c87110e79ac162461fc12b2dca3b2d4e03067a4515b0700ee6db4c1b14f5502a493a + languageName: node + linkType: hard + +"@smithy/config-resolver@npm:^4.1.2, @smithy/config-resolver@npm:^4.1.3": + version: 4.1.3 + resolution: "@smithy/config-resolver@npm:4.1.3" + dependencies: + "@smithy/node-config-provider": "npm:^4.1.2" + "@smithy/types": "npm:^4.3.0" + "@smithy/util-config-provider": "npm:^4.0.0" + "@smithy/util-middleware": "npm:^4.0.3" + tslib: "npm:^2.6.2" + checksum: 10/b32d9d719f69a75a2dd0933f6e714ed6cd0d80c86e88706e8fe835d66e04ece50e5fe2daa27043178163836b2611952cc40829a0d28c3f82b1b30fbc3350f4b4 + languageName: node + linkType: hard + +"@smithy/core@npm:^3.3.3, @smithy/core@npm:^3.4.0": + version: 3.4.0 + resolution: "@smithy/core@npm:3.4.0" + dependencies: + "@smithy/middleware-serde": "npm:^4.0.6" + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/types": "npm:^4.3.0" + "@smithy/util-body-length-browser": "npm:^4.0.0" + "@smithy/util-middleware": "npm:^4.0.3" + "@smithy/util-stream": "npm:^4.2.1" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/f08310266485cdb854a78d00f875bd60c68db62159de3516b096a3a57ee49947fcd8292b1611eca5e51ad90906987b7d494ba9dc9f8acc910912483c62faafd6 + languageName: node + linkType: hard + +"@smithy/credential-provider-imds@npm:^4.0.4, @smithy/credential-provider-imds@npm:^4.0.5": + version: 4.0.5 + resolution: "@smithy/credential-provider-imds@npm:4.0.5" + dependencies: + "@smithy/node-config-provider": "npm:^4.1.2" + "@smithy/property-provider": "npm:^4.0.3" + "@smithy/types": "npm:^4.3.0" + "@smithy/url-parser": "npm:^4.0.3" + tslib: "npm:^2.6.2" + checksum: 10/204e3c5f5899a76164e27bf3cc96b66d8423954e48537962dfa0060a8f922518c2394f27ba940b795ca1347384f2fae72b0ab6043375c0e16217d334e42bf703 + languageName: node + linkType: hard + +"@smithy/fetch-http-handler@npm:^5.0.2, @smithy/fetch-http-handler@npm:^5.0.3": + version: 5.0.3 + resolution: "@smithy/fetch-http-handler@npm:5.0.3" + dependencies: + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/querystring-builder": "npm:^4.0.3" + "@smithy/types": "npm:^4.3.0" + "@smithy/util-base64": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/bc0ac0882f20cbfaf2668eb3cd8935496658cf4e6d72a436ac7b789d8ce3b3b0621236d83ca271d7a1b7265565cc03647157c0b0a777198e06b8e5f3f997540b + languageName: node + linkType: hard + +"@smithy/hash-node@npm:^4.0.2": + version: 4.0.3 + resolution: "@smithy/hash-node@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + "@smithy/util-buffer-from": "npm:^4.0.0" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/9f9aa9fb25cc91416e0548018b594eaa968a1d294d4ae632b55108aa6388123f7ded52a7b20144e1b735dc3f8a34755dba2754e2d4691413007ed5d29aff77f0 + languageName: node + linkType: hard + +"@smithy/invalid-dependency@npm:^4.0.2": + version: 4.0.3 + resolution: "@smithy/invalid-dependency@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/155d1097c9faf61bc728ba179965283e7010583b5c4873a240becc6e8ec2a88fe9b13efb4b720ceb2b67a04d46b11bd82236640cbe87d04c303cab922c1b3c11 + languageName: node + linkType: hard + +"@smithy/is-array-buffer@npm:^2.2.0": + version: 2.2.0 + resolution: "@smithy/is-array-buffer@npm:2.2.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10/d366743ecc7a9fc3bad21dbb3950d213c12bdd4aeb62b1265bf6cbe38309df547664ef3e51ab732e704485194f15e89d361943b0bfbe3fe1a4b3178b942913cc + languageName: node + linkType: hard + +"@smithy/is-array-buffer@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/is-array-buffer@npm:4.0.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10/3985046ac490968fe86e2d5e87d023d67f29aa4778abebacecb0f7962d07e32507a5612701c7aa7b1fb63b5a6e68086c915cae5229e5f1abfb39419dc07e00c8 + languageName: node + linkType: hard + +"@smithy/middleware-content-length@npm:^4.0.2": + version: 4.0.3 + resolution: "@smithy/middleware-content-length@npm:4.0.3" + dependencies: + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/65f13e41243417ed078d11c5b380831fc13b911f30dc7b9110f3d425455e19bd270e62b63ea5bc1cffc2cd17f73eda2669d3802560ffeac9508a683bdf8d7aab + languageName: node + linkType: hard + +"@smithy/middleware-endpoint@npm:^4.1.6, @smithy/middleware-endpoint@npm:^4.1.7": + version: 4.1.7 + resolution: "@smithy/middleware-endpoint@npm:4.1.7" + dependencies: + "@smithy/core": "npm:^3.4.0" + "@smithy/middleware-serde": "npm:^4.0.6" + "@smithy/node-config-provider": "npm:^4.1.2" + "@smithy/shared-ini-file-loader": "npm:^4.0.3" + "@smithy/types": "npm:^4.3.0" + "@smithy/url-parser": "npm:^4.0.3" + "@smithy/util-middleware": "npm:^4.0.3" + tslib: "npm:^2.6.2" + checksum: 10/11301a1957e8d6bc369a47a4c627b1708448d7fd3252c9bb9b7af8ccc1c8e7165e79502c76d69736f86ac1ab84c488539de3477b4be9f28e47c9fa36adf642ae + languageName: node + linkType: hard + +"@smithy/middleware-retry@npm:^4.1.7": + version: 4.1.8 + resolution: "@smithy/middleware-retry@npm:4.1.8" + dependencies: + "@smithy/node-config-provider": "npm:^4.1.2" + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/service-error-classification": "npm:^4.0.4" + "@smithy/smithy-client": "npm:^4.3.0" + "@smithy/types": "npm:^4.3.0" + "@smithy/util-middleware": "npm:^4.0.3" + "@smithy/util-retry": "npm:^4.0.4" + tslib: "npm:^2.6.2" + uuid: "npm:^9.0.1" + checksum: 10/8437f443e0fd724787665a2ca35077ba20ae8cda5e0485c0fb64d5dffb465ecda76a7429296ea59b78637b68371e1ee70a1d151310507c900ab69bd77f587626 + languageName: node + linkType: hard + +"@smithy/middleware-serde@npm:^4.0.5, @smithy/middleware-serde@npm:^4.0.6": + version: 4.0.6 + resolution: "@smithy/middleware-serde@npm:4.0.6" + dependencies: + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/85e3da9116888d565bc448839ec3508a270c6f51871a1d88716baf53e1dd7c6cc3ea7417f068ccb0ce5524c31751f753323d543ad663109a69e34f58b04352a0 + languageName: node + linkType: hard + +"@smithy/middleware-stack@npm:^4.0.2, @smithy/middleware-stack@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/middleware-stack@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/1e7b77e8d065e04277c998ca110922594d1de7a96458784744e4478ca9bac18575d586419a0af2cb17dcc1fe8bbb054796af5f70bc1f6e37d1bf005411694e00 + languageName: node + linkType: hard + +"@smithy/node-config-provider@npm:^4.1.1, @smithy/node-config-provider@npm:^4.1.2": + version: 4.1.2 + resolution: "@smithy/node-config-provider@npm:4.1.2" + dependencies: + "@smithy/property-provider": "npm:^4.0.3" + "@smithy/shared-ini-file-loader": "npm:^4.0.3" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/0bf7bddf1101d54039e40d2526ad736a333eafe6dcc55b18f83befa20cc02def8cb35864a0201c4150671d633a3ff9fc3f4dac8293a8584f8fd337eb8cc998b3 + languageName: node + linkType: hard + +"@smithy/node-http-handler@npm:^4.0.4, @smithy/node-http-handler@npm:^4.0.5": + version: 4.0.5 + resolution: "@smithy/node-http-handler@npm:4.0.5" + dependencies: + "@smithy/abort-controller": "npm:^4.0.3" + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/querystring-builder": "npm:^4.0.3" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/535e7946f801c70a4dc7f84d13db8177dd98e728ed91a5485f7c4e656f8c26ad2b43381a9260b05b073556a416b7f6d83ab0774c334465d5f72606d2a5dfa87d + languageName: node + linkType: hard + +"@smithy/property-provider@npm:^4.0.2, @smithy/property-provider@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/property-provider@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/dce9b104f20f5364b9d7036f02e15f211ec6c8fbada034c759a9c2851eac83b9e1faea4bc8a5ec29e89bbbe745de61fe9cdb9863d611c8356732496e2e5fa3bd + languageName: node + linkType: hard + +"@smithy/protocol-http@npm:^5.1.0, @smithy/protocol-http@npm:^5.1.1": + version: 5.1.1 + resolution: "@smithy/protocol-http@npm:5.1.1" + dependencies: + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/56b5b6a7c2ba99491193daa8787305b65a4f90483d51777fecf477f9386e1703912772502d535de34120c6ae2b628d44834749b1e02daded138f472c5847b9eb + languageName: node + linkType: hard + +"@smithy/querystring-builder@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/querystring-builder@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + "@smithy/util-uri-escape": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/a671e20dcf23d67613fbd1ee9ba5c04249d791e87bf55226351f43de8653ebc876c2117e224266ecfcb48725c90c25bfdc507dfcda0ecacdff92214a9fb7f23d + languageName: node + linkType: hard + +"@smithy/querystring-parser@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/querystring-parser@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/3d6b2f254f315989eb0ea2c187f6a7c2a96e9829f0ffda63f56f3003b8ddcc3cb8a195ad8608b2aaf6b855ee70c9fe2b0f66a3a6a2111cb1f6de50d627dad1e5 + languageName: node + linkType: hard + +"@smithy/service-error-classification@npm:^4.0.4": + version: 4.0.4 + resolution: "@smithy/service-error-classification@npm:4.0.4" + dependencies: + "@smithy/types": "npm:^4.3.0" + checksum: 10/8d821bf7fb50d141437400c451659a923fbb00325741996d68064441ed7317347f7b98890ff9bb57e4c2a0dd91580c56b23f267fef31e794402d0d44f406f9cc + languageName: node + linkType: hard + +"@smithy/shared-ini-file-loader@npm:^4.0.2, @smithy/shared-ini-file-loader@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/shared-ini-file-loader@npm:4.0.3" + dependencies: + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/a389c3dbc844eda79df506b90ca28e0d1e8c247d534e5adc043837cea7afb36e9d5dfbd0759524ee854986b1d443f2dfd5c6c0713a37e86ff7946dc3920ac2f5 + languageName: node + linkType: hard + +"@smithy/signature-v4@npm:^5.1.0": + version: 5.1.1 + resolution: "@smithy/signature-v4@npm:5.1.1" + dependencies: + "@smithy/is-array-buffer": "npm:^4.0.0" + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/types": "npm:^4.3.0" + "@smithy/util-hex-encoding": "npm:^4.0.0" + "@smithy/util-middleware": "npm:^4.0.3" + "@smithy/util-uri-escape": "npm:^4.0.0" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/b23ab5f94d9891cfa3562d4999c058534a543e8f01109267af39657f2e559dcc2b2c6c4aa102acad3c4e0e553a144edbd038d1abc0a9338c0e49ee4523e5bd6e + languageName: node + linkType: hard + +"@smithy/smithy-client@npm:^4.2.6, @smithy/smithy-client@npm:^4.3.0": + version: 4.3.0 + resolution: "@smithy/smithy-client@npm:4.3.0" + dependencies: + "@smithy/core": "npm:^3.4.0" + "@smithy/middleware-endpoint": "npm:^4.1.7" + "@smithy/middleware-stack": "npm:^4.0.3" + "@smithy/protocol-http": "npm:^5.1.1" + "@smithy/types": "npm:^4.3.0" + "@smithy/util-stream": "npm:^4.2.1" + tslib: "npm:^2.6.2" + checksum: 10/4c30258bfe1d4eeae2c6cf47ef9e2986718fe2cd35b53c65148dda266155b6afd4b10a306b6e0657b1d76b5a7c791cb4c780ad9165392cf591370926e49166e8 + languageName: node + linkType: hard + +"@smithy/types@npm:^4.2.0, @smithy/types@npm:^4.3.0": + version: 4.3.0 + resolution: "@smithy/types@npm:4.3.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10/ee80b47e5ec14c1acb5b29225f0e71709e6238eb239e46e92864f108f8af9d2c744efd0a31265d8739f90b31e4a815240c2a633c6f0b193c3c6c45f14eb5252d + languageName: node + linkType: hard + +"@smithy/url-parser@npm:^4.0.2, @smithy/url-parser@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/url-parser@npm:4.0.3" + dependencies: + "@smithy/querystring-parser": "npm:^4.0.3" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/9626289aa03961ad6307fed215e45abc7f4b0bbd5828be3cc109779f7a24968b1a2fb17b400a03ff335c6b772040e4adb92f4b83ff22f844ef7f2f2008f701a5 + languageName: node + linkType: hard + +"@smithy/util-base64@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-base64@npm:4.0.0" + dependencies: + "@smithy/util-buffer-from": "npm:^4.0.0" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/f495fa8f5be60a1b94f88e2de4b1236df5cfee78f32191840adffcc520f2f55cdc2f287dd7abddcac4759c51970b5326b6b371c60ad65b640992018e95e30d19 + languageName: node + linkType: hard + +"@smithy/util-body-length-browser@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-body-length-browser@npm:4.0.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10/041a5e3c98d5b0a935c992c0217dcc033886798406df803945c994fbf3302eb0d9bdea7f7f8e6abaabf3e547bdffda6f1fb00829be3e93adac6b1949d77b741f + languageName: node + linkType: hard + +"@smithy/util-body-length-node@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-body-length-node@npm:4.0.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10/28d7b25b1465b290507b90be595bb161f9c1de755b35b4b99c3cf752725806b7d1f0c364535007f45a6aba95f2b49c2be9ebabaa4f03b5d36f9fc3287cd9d17a + languageName: node + linkType: hard + +"@smithy/util-buffer-from@npm:^2.2.0": + version: 2.2.0 + resolution: "@smithy/util-buffer-from@npm:2.2.0" + dependencies: + "@smithy/is-array-buffer": "npm:^2.2.0" + tslib: "npm:^2.6.2" + checksum: 10/53253e4e351df3c4b7907dca48a0a6ceae783e98a8e73526820b122b3047a53fd127c19f4d8301f68d852011d821da519da783de57e0b22eed57c4df5b90d089 + languageName: node + linkType: hard + +"@smithy/util-buffer-from@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-buffer-from@npm:4.0.0" + dependencies: + "@smithy/is-array-buffer": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/077fd6fe88b9db69ef0d4e2dfa9946bb1e1ae3d899515d7102f8648d18fb012fcbc87244cce569c0e9e86c5001bfe309b2de874fe508e1a9a591b11540b0a2c8 + languageName: node + linkType: hard + +"@smithy/util-config-provider@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-config-provider@npm:4.0.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10/74f3cb317056f0974b0942c79d43859031cb860fcf6eb5c9244bee369fc6c4b9c823491a40ca4f03f65641f4128d7fa5c2d322860cb7ee8517c0b2e63088ac6f + languageName: node + linkType: hard + +"@smithy/util-defaults-mode-browser@npm:^4.0.14": + version: 4.0.15 + resolution: "@smithy/util-defaults-mode-browser@npm:4.0.15" + dependencies: + "@smithy/property-provider": "npm:^4.0.3" + "@smithy/smithy-client": "npm:^4.3.0" + "@smithy/types": "npm:^4.3.0" + bowser: "npm:^2.11.0" + tslib: "npm:^2.6.2" + checksum: 10/ef05f70979443a404f3dd86a4bac992fc517ffd6db0dd16fe347573cae1f398237c48e39727eddfbdb57baaf4cd57478ee59ce2b22e11fd157db8009f38e44a1 + languageName: node + linkType: hard + +"@smithy/util-defaults-mode-node@npm:^4.0.14": + version: 4.0.15 + resolution: "@smithy/util-defaults-mode-node@npm:4.0.15" + dependencies: + "@smithy/config-resolver": "npm:^4.1.3" + "@smithy/credential-provider-imds": "npm:^4.0.5" + "@smithy/node-config-provider": "npm:^4.1.2" + "@smithy/property-provider": "npm:^4.0.3" + "@smithy/smithy-client": "npm:^4.3.0" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/8fdebf845f7de1c254ce843fbd06ce2fe4989b79686ca33fee5bb3ef0a0f9fcb64db3c2d3cb0cdb705d279e115b2a5879b637f9ad795c6c34a5d73dfe278d692 + languageName: node + linkType: hard + +"@smithy/util-endpoints@npm:^3.0.4": + version: 3.0.5 + resolution: "@smithy/util-endpoints@npm:3.0.5" + dependencies: + "@smithy/node-config-provider": "npm:^4.1.2" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/260302b09f6a770f5a852833e6b4f2861ad28aab64ca7c44f9c128fbaf4575ea2755801d555d66429940a90c7ed865828b04f0e55cb28551cdb76599db96dcfb + languageName: node + linkType: hard + +"@smithy/util-hex-encoding@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-hex-encoding@npm:4.0.0" dependencies: - "@nodelib/fs.scandir": "npm:2.1.3" - fastq: "npm:^1.6.0" - checksum: 10/31b13e243cc7f8656e936be684f16f81ede62c3be5968f832ca9dab385db0c3bcd537aeb139bdec4cdb6973ba55035069978397a0d08317b7023e53128e915bd + tslib: "npm:^2.6.2" + checksum: 10/447475cad8510d2727bbdf8490021a7ca8cb52b391f4bfe646c73a3aa1d5678152f1b5c4c2aaeebd9f6650272d973a1739e2d42294bd68c957429e3a30db3546 languageName: node linkType: hard -"@nodelib/fs.walk@npm:^1.2.8": - version: 1.2.8 - resolution: "@nodelib/fs.walk@npm:1.2.8" +"@smithy/util-middleware@npm:^4.0.2, @smithy/util-middleware@npm:^4.0.3": + version: 4.0.3 + resolution: "@smithy/util-middleware@npm:4.0.3" dependencies: - "@nodelib/fs.scandir": "npm:2.1.5" - fastq: "npm:^1.6.0" - checksum: 10/40033e33e96e97d77fba5a238e4bba4487b8284678906a9f616b5579ddaf868a18874c0054a75402c9fbaaa033a25ceae093af58c9c30278e35c23c9479e79b0 + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/17057f18f5b70edfd4729852491dd0259df1a94e544969e604d675e421f5b748634e41361732505caa747c06d510ac8d948f9522ae52022e79bfa28a56238de1 languageName: node linkType: hard -"@npmcli/fs@npm:^2.1.0": - version: 2.1.2 - resolution: "@npmcli/fs@npm:2.1.2" +"@smithy/util-retry@npm:^4.0.3, @smithy/util-retry@npm:^4.0.4": + version: 4.0.4 + resolution: "@smithy/util-retry@npm:4.0.4" dependencies: - "@gar/promisify": "npm:^1.1.3" - semver: "npm:^7.3.5" - checksum: 10/c5d4dfee80de2236e1e4ed595d17e217aada72ebd8215183fc46096fa010f583dd2aaaa486758de7cc0b89440dbc31cfe8b276269d75d47af35c716e896f78ec + "@smithy/service-error-classification": "npm:^4.0.4" + "@smithy/types": "npm:^4.3.0" + tslib: "npm:^2.6.2" + checksum: 10/243e0e48092007281f2732c8267deadb8d6991ec900ed59b13005617cbfae2d715470d9cacb5aa819bbffc1dc30fc0bf1c1a27b5d8f2ec8ed3f24077bc627601 languageName: node linkType: hard -"@npmcli/move-file@npm:^2.0.0": - version: 2.0.1 - resolution: "@npmcli/move-file@npm:2.0.1" +"@smithy/util-stream@npm:^4.2.0, @smithy/util-stream@npm:^4.2.1": + version: 4.2.1 + resolution: "@smithy/util-stream@npm:4.2.1" dependencies: - mkdirp: "npm:^1.0.4" - rimraf: "npm:^3.0.2" - checksum: 10/52dc02259d98da517fae4cb3a0a3850227bdae4939dda1980b788a7670636ca2b4a01b58df03dd5f65c1e3cb70c50fa8ce5762b582b3f499ec30ee5ce1fd9380 + "@smithy/fetch-http-handler": "npm:^5.0.3" + "@smithy/node-http-handler": "npm:^4.0.5" + "@smithy/types": "npm:^4.3.0" + "@smithy/util-base64": "npm:^4.0.0" + "@smithy/util-buffer-from": "npm:^4.0.0" + "@smithy/util-hex-encoding": "npm:^4.0.0" + "@smithy/util-utf8": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/1e3639829cd93c5e1fb20550092a52f12ca31e0a23ec53e0409b9927731522fe149534e2f31fdde5eb32b15498d9516b30bb396cd017c9b0120f4f3d9ccab79d languageName: node linkType: hard -"@rollup/plugin-virtual@npm:^3.0.2": - version: 3.0.2 - resolution: "@rollup/plugin-virtual@npm:3.0.2" - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 10/962bc9efece57a07c328a3d093bd1a62b9b4396a88640ac79cfc04181e06b31c4b37726ca27ded71178ace27db9b0085b43c4de823378773bb44cb233ea1340e +"@smithy/util-uri-escape@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-uri-escape@npm:4.0.0" + dependencies: + tslib: "npm:^2.6.2" + checksum: 10/27b71d7c1bc21d9038b86fd55380449a7a1dab52959566372d24a86df027c0ad9190980879cc4903be999dc36a5619f0794acf9cdc789adba5e57e26cd6ce4a6 languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.13.0" - conditions: os=android & cpu=arm +"@smithy/util-utf8@npm:^2.0.0": + version: 2.3.0 + resolution: "@smithy/util-utf8@npm:2.3.0" + dependencies: + "@smithy/util-buffer-from": "npm:^2.2.0" + tslib: "npm:^2.6.2" + checksum: 10/c766ead8dac6bc6169f4cac1cc47ef7bd86928d06255148f9528228002f669c8cc49f78dc2b9ba5d7e214d40315024a9e32c5c9130b33e20f0fe4532acd0dff5 languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-android-arm64@npm:4.13.0" - conditions: os=android & cpu=arm64 +"@smithy/util-utf8@npm:^4.0.0": + version: 4.0.0 + resolution: "@smithy/util-utf8@npm:4.0.0" + dependencies: + "@smithy/util-buffer-from": "npm:^4.0.0" + tslib: "npm:^2.6.2" + checksum: 10/4de06914d08753ce14ec553cf2dabe4a432cf982e415ec7dec82dfb8a6af793ddd08587fbcaeb889a0f6cc917eecca3a026880cf914082ee8e293f5bfc44e248 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-darwin-arm64@npm:4.13.0" +"@swc/core-darwin-arm64@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-darwin-arm64@npm:1.11.29" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-darwin-x64@npm:4.13.0" +"@swc/core-darwin-x64@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-darwin-x64@npm:1.11.29" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.13.0" +"@swc/core-linux-arm-gnueabihf@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.11.29" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.13.0" +"@swc/core-linux-arm64-gnu@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-linux-arm64-gnu@npm:1.11.29" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.13.0" +"@swc/core-linux-arm64-musl@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-linux-arm64-musl@npm:1.11.29" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.13.0" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - -"@rollup/rollup-linux-x64-gnu@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.13.0" +"@swc/core-linux-x64-gnu@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-linux-x64-gnu@npm:1.11.29" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.13.0" +"@swc/core-linux-x64-musl@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-linux-x64-musl@npm:1.11.29" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.13.0" +"@swc/core-win32-arm64-msvc@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-win32-arm64-msvc@npm:1.11.29" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.13.0" +"@swc/core-win32-ia32-msvc@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-win32-ia32-msvc@npm:1.11.29" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.13.0": - version: 4.13.0 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.13.0" +"@swc/core-win32-x64-msvc@npm:1.11.29": + version: 1.11.29 + resolution: "@swc/core-win32-x64-msvc@npm:1.11.29" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@smithy/protocol-http@npm:^1.0.1": - version: 1.0.1 - resolution: "@smithy/protocol-http@npm:1.0.1" +"@swc/core@npm:^1.10.16": + version: 1.11.29 + resolution: "@swc/core@npm:1.11.29" dependencies: - "@smithy/types": "npm:^1.0.0" - tslib: "npm:^2.5.0" - checksum: 10/ce35abbe2a82e395eaafbb339e338b43a691b26923a6e95cc0bf1b3001ccf3ccbd7c746e62f6c36e3675b5255915ac08e3ec84b90ca0f7a9f729f67164467313 + "@swc/core-darwin-arm64": "npm:1.11.29" + "@swc/core-darwin-x64": "npm:1.11.29" + "@swc/core-linux-arm-gnueabihf": "npm:1.11.29" + "@swc/core-linux-arm64-gnu": "npm:1.11.29" + "@swc/core-linux-arm64-musl": "npm:1.11.29" + "@swc/core-linux-x64-gnu": "npm:1.11.29" + "@swc/core-linux-x64-musl": "npm:1.11.29" + "@swc/core-win32-arm64-msvc": "npm:1.11.29" + "@swc/core-win32-ia32-msvc": "npm:1.11.29" + "@swc/core-win32-x64-msvc": "npm:1.11.29" + "@swc/counter": "npm:^0.1.3" + "@swc/types": "npm:^0.1.21" + peerDependencies: + "@swc/helpers": ">=0.5.17" + dependenciesMeta: + "@swc/core-darwin-arm64": + optional: true + "@swc/core-darwin-x64": + optional: true + "@swc/core-linux-arm-gnueabihf": + optional: true + "@swc/core-linux-arm64-gnu": + optional: true + "@swc/core-linux-arm64-musl": + optional: true + "@swc/core-linux-x64-gnu": + optional: true + "@swc/core-linux-x64-musl": + optional: true + "@swc/core-win32-arm64-msvc": + optional: true + "@swc/core-win32-ia32-msvc": + optional: true + "@swc/core-win32-x64-msvc": + optional: true + peerDependenciesMeta: + "@swc/helpers": + optional: true + checksum: 10/6945229bf6da91adff26033910e8e02ccc457a8229724d0539a0b32995d05949c7709cb9cae2cd7ab10cf4d346b235e22dd4d6b207ded765597304e21e6b6101 languageName: node linkType: hard -"@smithy/types@npm:^1.0.0": - version: 1.0.0 - resolution: "@smithy/types@npm:1.0.0" +"@swc/counter@npm:^0.1.3": + version: 0.1.3 + resolution: "@swc/counter@npm:0.1.3" + checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 + languageName: node + linkType: hard + +"@swc/types@npm:^0.1.21": + version: 0.1.21 + resolution: "@swc/types@npm:0.1.21" + dependencies: + "@swc/counter": "npm:^0.1.3" + checksum: 10/6554bf5c78519f49099a2ba448d170191a14b1c7a35df848f10ee4d6c03ecd681e5213884905187de1d1d221589ec8b5cb77f477d099dc1627c3ec9d7f2fcdb0 + languageName: node + linkType: hard + +"@tailwindcss/node@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/node@npm:4.1.7" dependencies: - tslib: "npm:^2.5.0" - checksum: 10/f0a6942ee6358456094d56365663a859fd3bacb9b1c290beefd7308fe08a66b5423fe95f80156b6bbb177c1549cdd1e9a6e4b854e868b87a0f3a8f2b1ad91c86 + "@ampproject/remapping": "npm:^2.3.0" + enhanced-resolve: "npm:^5.18.1" + jiti: "npm:^2.4.2" + lightningcss: "npm:1.30.1" + magic-string: "npm:^0.30.17" + source-map-js: "npm:^1.2.1" + tailwindcss: "npm:4.1.7" + checksum: 10/df645e89098c0046609e32245c94722e4af9f2790fc9c4a85c8b4405b3eb578e5e16ea6da666585f7e4af2dde40829ea88cc994ace550ec94f7133cd97b50285 + languageName: node + linkType: hard + +"@tailwindcss/oxide-android-arm64@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-android-arm64@npm:4.1.7" + conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-darwin-arm64@npm:1.4.8" +"@tailwindcss/oxide-darwin-arm64@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-darwin-arm64@npm:4.1.7" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-darwin-x64@npm:1.4.8" +"@tailwindcss/oxide-darwin-x64@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-darwin-x64@npm:4.1.7" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.4.8" +"@tailwindcss/oxide-freebsd-x64@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-freebsd-x64@npm:4.1.7" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.1.7" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-linux-arm64-gnu@npm:1.4.8" +"@tailwindcss/oxide-linux-arm64-gnu@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-linux-arm64-gnu@npm:4.1.7" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-linux-arm64-musl@npm:1.4.8" +"@tailwindcss/oxide-linux-arm64-musl@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-linux-arm64-musl@npm:4.1.7" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-linux-x64-gnu@npm:1.4.8" +"@tailwindcss/oxide-linux-x64-gnu@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-linux-x64-gnu@npm:4.1.7" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-linux-x64-musl@npm:1.4.8" +"@tailwindcss/oxide-linux-x64-musl@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-linux-x64-musl@npm:4.1.7" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-win32-arm64-msvc@npm:1.4.8" - conditions: os=win32 & cpu=arm64 +"@tailwindcss/oxide-wasm32-wasi@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-wasm32-wasi@npm:4.1.7" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@emnapi/wasi-threads": "npm:^1.0.2" + "@napi-rs/wasm-runtime": "npm:^0.2.9" + "@tybys/wasm-util": "npm:^0.9.0" + tslib: "npm:^2.8.0" + conditions: cpu=wasm32 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-win32-ia32-msvc@npm:1.4.8" - conditions: os=win32 & cpu=ia32 +"@tailwindcss/oxide-win32-arm64-msvc@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-win32-arm64-msvc@npm:4.1.7" + conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.4.8": - version: 1.4.8 - resolution: "@swc/core-win32-x64-msvc@npm:1.4.8" +"@tailwindcss/oxide-win32-x64-msvc@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide-win32-x64-msvc@npm:4.1.7" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@swc/core@npm:^1.3.100": - version: 1.4.8 - resolution: "@swc/core@npm:1.4.8" - dependencies: - "@swc/core-darwin-arm64": "npm:1.4.8" - "@swc/core-darwin-x64": "npm:1.4.8" - "@swc/core-linux-arm-gnueabihf": "npm:1.4.8" - "@swc/core-linux-arm64-gnu": "npm:1.4.8" - "@swc/core-linux-arm64-musl": "npm:1.4.8" - "@swc/core-linux-x64-gnu": "npm:1.4.8" - "@swc/core-linux-x64-musl": "npm:1.4.8" - "@swc/core-win32-arm64-msvc": "npm:1.4.8" - "@swc/core-win32-ia32-msvc": "npm:1.4.8" - "@swc/core-win32-x64-msvc": "npm:1.4.8" - "@swc/counter": "npm:^0.1.2" - "@swc/types": "npm:^0.1.5" - peerDependencies: - "@swc/helpers": ^0.5.0 +"@tailwindcss/oxide@npm:4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/oxide@npm:4.1.7" + dependencies: + "@tailwindcss/oxide-android-arm64": "npm:4.1.7" + "@tailwindcss/oxide-darwin-arm64": "npm:4.1.7" + "@tailwindcss/oxide-darwin-x64": "npm:4.1.7" + "@tailwindcss/oxide-freebsd-x64": "npm:4.1.7" + "@tailwindcss/oxide-linux-arm-gnueabihf": "npm:4.1.7" + "@tailwindcss/oxide-linux-arm64-gnu": "npm:4.1.7" + "@tailwindcss/oxide-linux-arm64-musl": "npm:4.1.7" + "@tailwindcss/oxide-linux-x64-gnu": "npm:4.1.7" + "@tailwindcss/oxide-linux-x64-musl": "npm:4.1.7" + "@tailwindcss/oxide-wasm32-wasi": "npm:4.1.7" + "@tailwindcss/oxide-win32-arm64-msvc": "npm:4.1.7" + "@tailwindcss/oxide-win32-x64-msvc": "npm:4.1.7" + detect-libc: "npm:^2.0.4" + tar: "npm:^7.4.3" dependenciesMeta: - "@swc/core-darwin-arm64": + "@tailwindcss/oxide-android-arm64": optional: true - "@swc/core-darwin-x64": + "@tailwindcss/oxide-darwin-arm64": optional: true - "@swc/core-linux-arm-gnueabihf": + "@tailwindcss/oxide-darwin-x64": optional: true - "@swc/core-linux-arm64-gnu": + "@tailwindcss/oxide-freebsd-x64": optional: true - "@swc/core-linux-arm64-musl": + "@tailwindcss/oxide-linux-arm-gnueabihf": optional: true - "@swc/core-linux-x64-gnu": + "@tailwindcss/oxide-linux-arm64-gnu": optional: true - "@swc/core-linux-x64-musl": + "@tailwindcss/oxide-linux-arm64-musl": optional: true - "@swc/core-win32-arm64-msvc": + "@tailwindcss/oxide-linux-x64-gnu": optional: true - "@swc/core-win32-ia32-msvc": + "@tailwindcss/oxide-linux-x64-musl": optional: true - "@swc/core-win32-x64-msvc": + "@tailwindcss/oxide-wasm32-wasi": optional: true - peerDependenciesMeta: - "@swc/helpers": + "@tailwindcss/oxide-win32-arm64-msvc": optional: true - checksum: 10/817b674130bc43345e7d8e7fbcf56658d4a655d9544c646475063c7849529c0a6c236a15f3217e7b0b2b99050bda189d3ff26e225b80b838a87b954b97abcb2a - languageName: node - linkType: hard - -"@swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3": - version: 0.1.3 - resolution: "@swc/counter@npm:0.1.3" - checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 + "@tailwindcss/oxide-win32-x64-msvc": + optional: true + checksum: 10/39c4c67667e30626ed123cff33ac651e0c64f7c15f759ff6b3456d1d7460728cf7d350716945af6d0ef67e12fc8f45853f9984436c9bf8594c5daad35a3cecac languageName: node linkType: hard -"@swc/types@npm:^0.1.5": - version: 0.1.6 - resolution: "@swc/types@npm:0.1.6" +"@tailwindcss/vite@npm:^4.1.7": + version: 4.1.7 + resolution: "@tailwindcss/vite@npm:4.1.7" dependencies: - "@swc/counter": "npm:^0.1.3" - checksum: 10/b42fbca6f1ad56d1909fa6114b62107418a665730bb9b4d8bd8fa1c86921f8758a73959928342638fb57490b5d618a46881045fa9f094763a00f939944835d36 + "@tailwindcss/node": "npm:4.1.7" + "@tailwindcss/oxide": "npm:4.1.7" + tailwindcss: "npm:4.1.7" + peerDependencies: + vite: ^5.2.0 || ^6 + checksum: 10/b70d85b312ef4fd129555f02492ceed687aa5f356d123cbc081b9444ab99f9f977e080bde18acfe212f64d49b4d65deef967ac05e88b152dadcbeafd16d0092c languageName: node linkType: hard -"@tootallnate/once@npm:2": - version: 2.0.0 - resolution: "@tootallnate/once@npm:2.0.0" - checksum: 10/ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 +"@tybys/wasm-util@npm:^0.9.0": + version: 0.9.0 + resolution: "@tybys/wasm-util@npm:0.9.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/aa58e64753a420ad1eefaf7bacef3dda61d74f9336925943d9244132d5b48d9242f734f1e707fd5ccfa6dd1d8ec8e6debc234b4dedb3a5b0d8486d1f373350b2 languageName: node linkType: hard @@ -1891,11 +2181,11 @@ __metadata: linkType: hard "@types/babel__generator@npm:*": - version: 7.6.8 - resolution: "@types/babel__generator@npm:7.6.8" + version: 7.27.0 + resolution: "@types/babel__generator@npm:7.27.0" dependencies: "@babel/types": "npm:^7.0.0" - checksum: 10/b53c215e9074c69d212402990b0ca8fa57595d09e10d94bda3130aa22b55d796e50449199867879e4ea0ee968f3a2099e009cfb21a726a53324483abbf25cd30 + checksum: 10/f572e67a9a39397664350a4437d8a7fbd34acc83ff4887a8cf08349e39f8aeb5ad2f70fb78a0a0a23a280affe3a5f4c25f50966abdce292bcf31237af1c27b1a languageName: node linkType: hard @@ -1910,77 +2200,70 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*": - version: 7.20.5 - resolution: "@types/babel__traverse@npm:7.20.5" + version: 7.20.7 + resolution: "@types/babel__traverse@npm:7.20.7" dependencies: "@babel/types": "npm:^7.20.7" - checksum: 10/f0352d537448e1e37f27e6bb8c962d7893720a92fde9d8601a68a93dbc14e15c088b4c0c8f71021d0966d09fba802ef3de11fdb6766c33993f8cf24f1277c6a9 + checksum: 10/d005b58e1c26bdafc1ce564f60db0ee938393c7fc586b1197bdb71a02f7f33f72bc10ae4165776b6cafc77c4b6f2e1a164dd20bc36518c471b1131b153b4baa6 languageName: node linkType: hard "@types/body-parser@npm:*": - version: 1.19.2 - resolution: "@types/body-parser@npm:1.19.2" + version: 1.19.5 + resolution: "@types/body-parser@npm:1.19.5" dependencies: "@types/connect": "npm:*" "@types/node": "npm:*" - checksum: 10/e17840c7d747a549f00aebe72c89313d09fbc4b632b949b2470c5cb3b1cb73863901ae84d9335b567a79ec5efcfb8a28ff8e3f36bc8748a9686756b6d5681f40 - languageName: node - linkType: hard - -"@types/color-name@npm:^1.1.1": - version: 1.1.1 - resolution: "@types/color-name@npm:1.1.1" - checksum: 10/73e0e230a6708210bcfc040f3bd3d7c4c0bf5ff7338e8e497cca3d05d20a0c29fb74a7bde0fa2cdf3322d4b1ffd5194c456712908974ae52d56c0d060ca55ae2 + checksum: 10/1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82 languageName: node linkType: hard "@types/connect@npm:*": - version: 3.4.35 - resolution: "@types/connect@npm:3.4.35" + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" dependencies: "@types/node": "npm:*" - checksum: 10/fe81351470f2d3165e8b12ce33542eef89ea893e36dd62e8f7d72566dfb7e448376ae962f9f3ea888547ce8b55a40020ca0e01d637fab5d99567673084542641 + checksum: 10/7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99 languageName: node linkType: hard "@types/cors@npm:^2.8.9": - version: 2.8.13 - resolution: "@types/cors@npm:2.8.13" + version: 2.8.18 + resolution: "@types/cors@npm:2.8.18" dependencies: "@types/node": "npm:*" - checksum: 10/7ef197ea19d2e5bf1313b8416baa6f3fd6dd887fd70191da1f804f557395357dafd8bc8bed0ac60686923406489262a7c8a525b55748f7b2b8afa686700de907 + checksum: 10/6e49b741345e67834cd19d766228509e4b37d6d5c272355bb059502b4787f5adf58776d9114ac5f0f407966e0347ae8d1f995d7ea41e6a24f716d36b3010401b languageName: node linkType: hard -"@types/estree@npm:1.0.5": - version: 1.0.5 - resolution: "@types/estree@npm:1.0.5" - checksum: 10/7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 +"@types/estree@npm:1.0.7": + version: 1.0.7 + resolution: "@types/estree@npm:1.0.7" + checksum: 10/419c845ece767ad4b21171e6e5b63dabb2eb46b9c0d97361edcd9cabbf6a95fcadb91d89b5fa098d1336fa0b8fceaea82fca97a2ef3971f5c86e53031e157b21 languageName: node linkType: hard "@types/express-serve-static-core@npm:^4.17.33": - version: 4.17.35 - resolution: "@types/express-serve-static-core@npm:4.17.35" + version: 4.19.6 + resolution: "@types/express-serve-static-core@npm:4.19.6" dependencies: "@types/node": "npm:*" "@types/qs": "npm:*" "@types/range-parser": "npm:*" "@types/send": "npm:*" - checksum: 10/9f08212ac163e9b2a1005d84cc43ace52d5057dfaa009c575eb3f3a659949b9c9cecec0cbff863622871c56e1c604bd67857a5e1d353256eaf9adacec59f87bf + checksum: 10/a2e00b6c5993f0dd63ada2239be81076fe0220314b9e9fde586e8946c9c09ce60f9a2dd0d74410ee2b5fd10af8c3e755a32bb3abf134533e2158142488995455 languageName: node linkType: hard "@types/express@npm:^4.17.7": - version: 4.17.17 - resolution: "@types/express@npm:4.17.17" + version: 4.17.22 + resolution: "@types/express@npm:4.17.22" dependencies: "@types/body-parser": "npm:*" "@types/express-serve-static-core": "npm:^4.17.33" "@types/qs": "npm:*" "@types/serve-static": "npm:*" - checksum: 10/e2959a5fecdc53f8a524891a16e66dfc330ee0519e89c2579893179db686e10cfa6079a68e0fb8fd00eedbcaf3eabfd10916461939f3bc02ef671d848532c37e + checksum: 10/9497634fc341ff4ac966ec0c529ded03bdacd2c3dae164f10a060ff250c66591b873aedce92d0239869cf3d05615ae9bcad584c7349fe68780242f6fef010c62 languageName: node linkType: hard @@ -1991,10 +2274,17 @@ __metadata: languageName: node linkType: hard +"@types/http-errors@npm:*": + version: 2.0.4 + resolution: "@types/http-errors@npm:2.0.4" + checksum: 10/1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3 + languageName: node + linkType: hard + "@types/json-schema@npm:^7.0.9": - version: 7.0.12 - resolution: "@types/json-schema@npm:7.0.12" - checksum: 10/7a72ba9cb7d2b45d7bb032e063c9eeb1ce4102d62551761e84c91f99f8273ba5aaffd34be835869456ec7c40761b4389009d9e777c0020a7227ca0f5e3238e94 + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 10/1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 languageName: node linkType: hard @@ -2007,17 +2297,10 @@ __metadata: languageName: node linkType: hard -"@types/mime@npm:*": - version: 3.0.1 - resolution: "@types/mime@npm:3.0.1" - checksum: 10/4040fac73fd0cea2460e29b348c1a6173da747f3a87da0dbce80dd7a9355a3d0e51d6d9a401654f3e5550620e3718b5a899b2ec1debf18424e298a2c605346e7 - languageName: node - linkType: hard - "@types/mime@npm:^1": - version: 1.3.2 - resolution: "@types/mime@npm:1.3.2" - checksum: 10/0493368244cced1a69cb791b485a260a422e6fcc857782e1178d1e6f219f1b161793e9f87f5fae1b219af0f50bee24fcbe733a18b4be8fdd07a38a8fb91146fd + version: 1.3.5 + resolution: "@types/mime@npm:1.3.5" + checksum: 10/e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78 languageName: node linkType: hard @@ -2031,107 +2314,102 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 20.3.0 - resolution: "@types/node@npm:20.3.0" - checksum: 10/c1fdc2d64313f53fbd0d2d4172e61b2e088c4474c2d33f448cbda54948bc52f56b0fb78d39f958d4add630cd91d03bee292a34615e94a05251b7a4cb335899de + version: 22.15.21 + resolution: "@types/node@npm:22.15.21" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10/cb4189587cca445bfb8166c0ed39f9344d743f37f3da892f2999a99bbabda45dc773237e61ecb7d1dc83dd95718cb1b5715b0be5dd7953565b19019e36a7cf39 languageName: node linkType: hard "@types/prop-types@npm:*": - version: 15.7.11 - resolution: "@types/prop-types@npm:15.7.11" - checksum: 10/7519ff11d06fbf6b275029fe03fff9ec377b4cb6e864cac34d87d7146c7f5a7560fd164bdc1d2dbe00b60c43713631251af1fd3d34d46c69cd354602bc0c7c54 + version: 15.7.14 + resolution: "@types/prop-types@npm:15.7.14" + checksum: 10/d0c5407b9ccc3dd5fae0ccf9b1007e7622ba5e6f1c18399b4f24dff33619d469da4b9fa918a374f19dc0d9fe6a013362aab0b844b606cfc10676efba3f5f736d languageName: node linkType: hard "@types/qs@npm:*": - version: 6.9.7 - resolution: "@types/qs@npm:6.9.7" - checksum: 10/7fd6f9c25053e9b5bb6bc9f9f76c1d89e6c04f7707a7ba0e44cc01f17ef5284adb82f230f542c2d5557d69407c9a40f0f3515e8319afd14e1e16b5543ac6cdba + version: 6.14.0 + resolution: "@types/qs@npm:6.14.0" + checksum: 10/1909205514d22b3cbc7c2314e2bd8056d5f05dfb21cf4377f0730ee5e338ea19957c41735d5e4806c746176563f50005bbab602d8358432e25d900bdf4970826 languageName: node linkType: hard "@types/range-parser@npm:*": - version: 1.2.4 - resolution: "@types/range-parser@npm:1.2.4" - checksum: 10/b7c0dfd5080a989d6c8bb0b6750fc0933d9acabeb476da6fe71d8bdf1ab65e37c136169d84148034802f48378ab94e3c37bb4ef7656b2bec2cb9c0f8d4146a95 + version: 1.2.7 + resolution: "@types/range-parser@npm:1.2.7" + checksum: 10/95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a languageName: node linkType: hard "@types/react-dom@npm:^18": - version: 18.2.22 - resolution: "@types/react-dom@npm:18.2.22" - dependencies: - "@types/react": "npm:*" - checksum: 10/310da22244c1bb65a7f213f8727bda821dd211cfb2dd62d1f9b28dd50ef1c196d59e908494bd5f25c13a3844343f3a6135f39fb830aca6f79646fa56c1b56c08 + version: 18.3.7 + resolution: "@types/react-dom@npm:18.3.7" + peerDependencies: + "@types/react": ^18.0.0 + checksum: 10/317569219366d487a3103ba1e5e47154e95a002915fdcf73a44162c48fe49c3a57fcf7f57fc6979e70d447112681e6b13c6c3c1df289db8b544df4aab2d318f3 languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:^18.2.67": - version: 18.2.67 - resolution: "@types/react@npm:18.2.67" +"@types/react@npm:^18.2.67": + version: 18.3.22 + resolution: "@types/react@npm:18.3.22" dependencies: "@types/prop-types": "npm:*" - "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/d7e248dbe8d9d3b05f0d8e128d615fc9c85aa2c5d15634271d20cb9b343dbeffb0875f31a44e7ac63b42afc25949bd4c3633b7ebee45ee4666591ca934a8dffb + checksum: 10/580496f2768db339206c215aba4347ca07cf5d87a825311355760c9018bf4e2020810a85e8c525681ab78aa53be1ccc3751c9f4ec9cbc0d1b8217c7aeaa62e32 languageName: node linkType: hard "@types/responselike@npm:^1.0.0": - version: 1.0.0 - resolution: "@types/responselike@npm:1.0.0" + version: 1.0.3 + resolution: "@types/responselike@npm:1.0.3" dependencies: "@types/node": "npm:*" - checksum: 10/e4972389457e4edce3cbba5e8474fb33684d73879433a9eec989d0afb7e550fd6fa3ffb8fe68dbb429288d10707796a193bc0007c4e8429fd267bdc4d8404632 - languageName: node - linkType: hard - -"@types/scheduler@npm:*": - version: 0.16.8 - resolution: "@types/scheduler@npm:0.16.8" - checksum: 10/6c091b096daa490093bf30dd7947cd28e5b2cd612ec93448432b33f724b162587fed9309a0acc104d97b69b1d49a0f3fc755a62282054d62975d53d7fd13472d + checksum: 10/6ac4b35723429b11b117e813c7acc42c3af8b5554caaf1fc750404c1ae59f9b7376bc69b9e9e194a5a97357a597c2228b7173d317320f0360d617b6425212f58 languageName: node linkType: hard "@types/seedrandom@npm:^3.0.4": - version: 3.0.5 - resolution: "@types/seedrandom@npm:3.0.5" - checksum: 10/d63d56ebc609203cf8cbe2ab7e7934237446bc2463ade664be130dcd4a3d74915d529909de2e1b18141cfabc9e42784998b7e5ff30c016919ac5b83911a700f0 + version: 3.0.8 + resolution: "@types/seedrandom@npm:3.0.8" + checksum: 10/9651de4ecb5ad060053678d6a42403dd78222bcca80016417c23b58b4f739e544b7197a78b97d6862cf417ea80fd2df612cc50ca0fa387fbe794e326a382ab0b languageName: node linkType: hard "@types/semver@npm:^7.3.12": - version: 7.5.0 - resolution: "@types/semver@npm:7.5.0" - checksum: 10/8fbfbf79e9c14c3c20160a42145a146cba44d9763d0fac78358b394dc36e41bc2590bc4f0129c6fcbbc9b30f12ea1ba821bfe84b29dc80897f315cc7dd251393 + version: 7.7.0 + resolution: "@types/semver@npm:7.7.0" + checksum: 10/ee4514c6c852b1c38f951239db02f9edeea39f5310fad9396a00b51efa2a2d96b3dfca1ae84c88181ea5b7157c57d32d7ef94edacee36fbf975546396b85ba5b languageName: node linkType: hard "@types/send@npm:*": - version: 0.17.1 - resolution: "@types/send@npm:0.17.1" + version: 0.17.4 + resolution: "@types/send@npm:0.17.4" dependencies: "@types/mime": "npm:^1" "@types/node": "npm:*" - checksum: 10/6420837887858f7aa82f2c0272f73edb42385bd0978f43095e83590a405d86c8cc6d918c30b2d542f1d8bddc9f3d16c2e8fdfca936940de71b97c45f228d1896 + checksum: 10/28320a2aa1eb704f7d96a65272a07c0bf3ae7ed5509c2c96ea5e33238980f71deeed51d3631927a77d5250e4091b3e66bce53b42d770873282c6a20bb8b0280d languageName: node linkType: hard "@types/serve-static@npm:*": - version: 1.15.1 - resolution: "@types/serve-static@npm:1.15.1" + version: 1.15.7 + resolution: "@types/serve-static@npm:1.15.7" dependencies: - "@types/mime": "npm:*" + "@types/http-errors": "npm:*" "@types/node": "npm:*" - checksum: 10/e556d611a4240d338afe90c080f9987bbeecee97f8fd3a8aabac07fa6bc3652a3c3f06214fb25f709547c4dcee9f0a723f24c799758484c6db7f46c0235d5b4f + "@types/send": "npm:*" + checksum: 10/c5a7171d5647f9fbd096ed1a26105759f3153ccf683824d99fee4c7eb9cde2953509621c56a070dd9fb1159e799e86d300cbe4e42245ebc5b0c1767e8ca94a67 languageName: node linkType: hard "@types/webidl-conversions@npm:*": - version: 7.0.0 - resolution: "@types/webidl-conversions@npm:7.0.0" - checksum: 10/60142c7ddd9eb6f907d232d6b3a81ecf990f73b5a62a004eba8bd0f54809a42ece68ce512e7e3e1d98af8b6393d66cddb96f3622d2fb223c4e9c8937c61bfed7 + version: 7.0.3 + resolution: "@types/webidl-conversions@npm:7.0.3" + checksum: 10/535ead9de4d3d6c8e4f4fa14e9db780d2a31e8020debc062f337e1420a41c3265e223e4f4b628f97a11ecf3b96390962cd88a9ffe34f44e159dec583ff49aa34 languageName: node linkType: hard @@ -2142,6 +2420,15 @@ __metadata: languageName: node linkType: hard +"@types/whatwg-url@npm:^11.0.2": + version: 11.0.5 + resolution: "@types/whatwg-url@npm:11.0.5" + dependencies: + "@types/webidl-conversions": "npm:*" + checksum: 10/23a0c45aff51817807b473a6adb181d6e3bb0d27dde54e84883d5d5bc93358e95204d2188e7ff7fdc2cdaf157e97e1188ef0a22ec79228da300fc30d4a05b56a + languageName: node + linkType: hard + "@types/whatwg-url@npm:^8.2.1": version: 8.2.2 resolution: "@types/whatwg-url@npm:8.2.2" @@ -2153,24 +2440,24 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.3": - version: 8.5.5 - resolution: "@types/ws@npm:8.5.5" + version: 8.18.1 + resolution: "@types/ws@npm:8.18.1" dependencies: "@types/node": "npm:*" - checksum: 10/b2d7da5bd469c2ff1ddcfba1da33a556dc02c539e727001e7dc7b4182935154143e96a101cc091686acefb4e115c8ee38111c6634934748b8dd2db0c851c50ab + checksum: 10/1ce05e3174dcacf28dae0e9b854ef1c9a12da44c7ed73617ab6897c5cbe4fccbb155a20be5508ae9a7dde2f83bd80f5cf3baa386b934fc4b40889ec963e94f3a languageName: node linkType: hard "@typescript-eslint/eslint-plugin@npm:^5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/eslint-plugin@npm:5.59.9" + version: 5.62.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" dependencies: "@eslint-community/regexpp": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:5.59.9" - "@typescript-eslint/type-utils": "npm:5.59.9" - "@typescript-eslint/utils": "npm:5.59.9" + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/type-utils": "npm:5.62.0" + "@typescript-eslint/utils": "npm:5.62.0" debug: "npm:^4.3.4" - grapheme-splitter: "npm:^1.0.4" + graphemer: "npm:^1.4.0" ignore: "npm:^5.2.0" natural-compare-lite: "npm:^1.4.0" semver: "npm:^7.3.7" @@ -2181,43 +2468,43 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/8d25afe8574930f6680a043f314449ac5063fa382e7ee4d346172ba514b140bf126d19da546d5d5f2946a7d2bbff139312cd98aa83c55506b50a17f3226780b5 + checksum: 10/9cc8319c6fd8a21938f5b69476974a7e778c283a55ef9fad183c850995b9adcb0087d57cea7b2ac6b9449570eee983aad39491d14cdd2e52d6b4b0485e7b2482 languageName: node linkType: hard "@typescript-eslint/parser@npm:^5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/parser@npm:5.59.9" + version: 5.62.0 + resolution: "@typescript-eslint/parser@npm:5.62.0" dependencies: - "@typescript-eslint/scope-manager": "npm:5.59.9" - "@typescript-eslint/types": "npm:5.59.9" - "@typescript-eslint/typescript-estree": "npm:5.59.9" + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/typescript-estree": "npm:5.62.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/49a0bb14165c4c6308ac8d777f3483c128c4357f4e7525e73e51e07b9e6c386c61dc041518c31337e34f789bd5af264255a9b98456f16feb7c245be52a23259c + checksum: 10/b6ca629d8f4e6283ff124501731cc886703eb4ce2c7d38b3e4110322ea21452b9d9392faf25be6bd72f54b89de7ffc72a40d9b159083ac54345a3d04b4fa5394 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/scope-manager@npm:5.59.9" +"@typescript-eslint/scope-manager@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/scope-manager@npm:5.62.0" dependencies: - "@typescript-eslint/types": "npm:5.59.9" - "@typescript-eslint/visitor-keys": "npm:5.59.9" - checksum: 10/83b538212fc422cd6a26eee49deab60a29fa6d8bbd0dffca6daa02318959c76ddf1dc00db9ce0236258f26c1f726be78a25d2f6c5603233f591716d6299480e5 + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/visitor-keys": "npm:5.62.0" + checksum: 10/e827770baa202223bc0387e2fd24f630690809e460435b7dc9af336c77322290a770d62bd5284260fa881c86074d6a9fd6c97b07382520b115f6786b8ed499da languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/type-utils@npm:5.59.9" +"@typescript-eslint/type-utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/type-utils@npm:5.62.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:5.59.9" - "@typescript-eslint/utils": "npm:5.59.9" + "@typescript-eslint/typescript-estree": "npm:5.62.0" + "@typescript-eslint/utils": "npm:5.62.0" debug: "npm:^4.3.4" tsutils: "npm:^3.21.0" peerDependencies: @@ -2225,23 +2512,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/a510ddf2783b1f70ff2a2242b5d45833036817e22649cfbc662f3b8427e98675b9d3e170747f90b3654a4ccfa97d3aee17bba708a74e35ce372f4704ac508dab + checksum: 10/f9a4398d6d2aae09e3e765eff04cf4ab364376a87868031ac5c6a64c9bbb555cb1a7f99b07b3d1017e7422725b5f0bbee537f13b82ab2d930f161c987b3dece0 languageName: node linkType: hard -"@typescript-eslint/types@npm:5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/types@npm:5.59.9" - checksum: 10/49226e5384ac801db245fe668b4bd7610a11c5ade9c05ee93767fd188462c4d25755b8592f21210cc9856fae3c5566d4811ed0f7fefe30e48e5823e71ab4623e +"@typescript-eslint/types@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/types@npm:5.62.0" + checksum: 10/24e8443177be84823242d6729d56af2c4b47bfc664dd411a1d730506abf2150d6c31bdefbbc6d97c8f91043e3a50e0c698239dcb145b79bb6b0c34469aaf6c45 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/typescript-estree@npm:5.59.9" +"@typescript-eslint/typescript-estree@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" dependencies: - "@typescript-eslint/types": "npm:5.59.9" - "@typescript-eslint/visitor-keys": "npm:5.59.9" + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/visitor-keys": "npm:5.62.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -2250,64 +2537,72 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/79cf330815244f2ab12762df9296812c20f3ff859f14dc997a79ce09eabd7c8d0d190ed00fcdf380288a2b4035ca40c9f0002dc9c6c2875885ad3b94c2eab58b + checksum: 10/06c975eb5f44b43bd19fadc2e1023c50cf87038fe4c0dd989d4331c67b3ff509b17fa60a3251896668ab4d7322bdc56162a9926971218d2e1a1874d2bef9a52e languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/utils@npm:5.59.9" +"@typescript-eslint/utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@types/json-schema": "npm:^7.0.9" "@types/semver": "npm:^7.3.12" - "@typescript-eslint/scope-manager": "npm:5.59.9" - "@typescript-eslint/types": "npm:5.59.9" - "@typescript-eslint/typescript-estree": "npm:5.59.9" + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/typescript-estree": "npm:5.62.0" eslint-scope: "npm:^5.1.1" semver: "npm:^7.3.7" peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10/e48429d9dd83d7ae1b95c64b35af790e36cd8c1b2b9b63b2f69b5f804bb58a12918396f2f0540afd413673e1e0d22399a2cd2e2ad6534e50af2990a04e8ca7c4 + checksum: 10/15ef13e43998a082b15f85db979f8d3ceb1f9ce4467b8016c267b1738d5e7cdb12aa90faf4b4e6dd6486c236cf9d33c463200465cf25ff997dbc0f12358550a1 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.59.9": - version: 5.59.9 - resolution: "@typescript-eslint/visitor-keys@npm:5.59.9" +"@typescript-eslint/visitor-keys@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" dependencies: - "@typescript-eslint/types": "npm:5.59.9" + "@typescript-eslint/types": "npm:5.62.0" eslint-visitor-keys: "npm:^3.3.0" - checksum: 10/85761ef0be6910cb4de841b3cd8f39a734f5373ed92f808365882ef357f0a33ad6f75c4b3bf0b408f0399781ac5d14f12033de3e4b53a46b61015444b05854c0 + checksum: 10/dc613ab7569df9bbe0b2ca677635eb91839dfb2ca2c6fa47870a5da4f160db0b436f7ec0764362e756d4164e9445d49d5eb1ff0b87f4c058946ae9d8c92eb388 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.2.0": + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10/80d6910946f2b1552a2406650051c91bbd1f24a6bf854354203d84fe2714b3e8ce4618f49cc3410494173a1c1e8e9777372fe68dce74bd45faf0a7a1a6ccf448 languageName: node linkType: hard "@vitejs/plugin-react@npm:^4.2.1": - version: 4.2.1 - resolution: "@vitejs/plugin-react@npm:4.2.1" + version: 4.5.0 + resolution: "@vitejs/plugin-react@npm:4.5.0" dependencies: - "@babel/core": "npm:^7.23.5" - "@babel/plugin-transform-react-jsx-self": "npm:^7.23.3" - "@babel/plugin-transform-react-jsx-source": "npm:^7.23.3" + "@babel/core": "npm:^7.26.10" + "@babel/plugin-transform-react-jsx-self": "npm:^7.25.9" + "@babel/plugin-transform-react-jsx-source": "npm:^7.25.9" + "@rolldown/pluginutils": "npm:1.0.0-beta.9" "@types/babel__core": "npm:^7.20.5" - react-refresh: "npm:^0.14.0" + react-refresh: "npm:^0.17.0" peerDependencies: - vite: ^4.2.0 || ^5.0.0 - checksum: 10/d7fa6dacd3c246bcee482ff4b7037b2978b6ca002b79780ad4921e91ae4bc85ab234cfb94f8d4d825fed8488a0acdda2ff02b47c27b3055187c0727b18fc725e + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + checksum: 10/0a1c4815fb5a404681443f6e3c4b5a82ec4527dc9fb606f9282bbff5d487b9af5e3433eee2386d4582045bcd691d1aca93df3cbf558164b763b7464710544fe8 languageName: node linkType: hard -"@zeit/schemas@npm:2.29.0": - version: 2.29.0 - resolution: "@zeit/schemas@npm:2.29.0" - checksum: 10/ad6afd42e77acdac32651ab594d8caafa0abe121db0de8858b276819a366f257d8b87476949c845e4e4293b24fa7c15def60b6e823ee7d65714dc9f150195e1b +"@zeit/schemas@npm:2.36.0": + version: 2.36.0 + resolution: "@zeit/schemas@npm:2.36.0" + checksum: 10/0d6e2ecf57f0e12c2b17dbdfa2f06f88519c1241275b5b8a1679dd591ee72fe45f5d87ef6ab35e068b07554b768c824dce3e2536f29d03c77cff4259209903e0 languageName: node linkType: hard -"abbrev@npm:1, abbrev@npm:^1.0.0": - version: 1.1.1 - resolution: "abbrev@npm:1.1.1" - checksum: 10/2d882941183c66aa665118bafdab82b7a177e9add5eb2776c33e960a4f3c89cff88a1b38aba13a456de01d0dd9d66a8bea7c903268b21ea91dd1097e1e2e8243 +"abbrev@npm:^3.0.0": + version: 3.0.1 + resolution: "abbrev@npm:3.0.1" + checksum: 10/ebd2c149dda6f543b66ce3779ea612151bb3aa9d0824f169773ee9876f1ca5a4e0adbcccc7eed048c04da7998e1825e2aa76fcca92d9e67dea50ac2b0a58dc2e languageName: node linkType: hard @@ -2330,66 +2625,43 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.8.0": - version: 8.8.2 - resolution: "acorn@npm:8.8.2" +"acorn@npm:^8.9.0": + version: 8.14.1 + resolution: "acorn@npm:8.14.1" bin: acorn: bin/acorn - checksum: 10/b4e77d56d24d3e11a45d9ac8ae661b4e14a4af04ae33edbf1e6bf910887e5bb352cc60e9ea06a0944880e6b658f58c095d3b54e88e1921cb9319608b51085dd7 - languageName: node - linkType: hard - -"agent-base@npm:6, agent-base@npm:^6.0.2": - version: 6.0.2 - resolution: "agent-base@npm:6.0.2" - dependencies: - debug: "npm:4" - checksum: 10/21fb903e0917e5cb16591b4d0ef6a028a54b83ac30cd1fca58dece3d4e0990512a8723f9f83130d88a41e2af8b1f7be1386fda3ea2d181bb1a62155e75e95e23 + checksum: 10/d1379bbee224e8d44c3c3946e6ba6973e999fbdd4e22e41c3455d7f9b6f72f7ce18d3dc218002e1e48eea789539cf1cb6d1430c81838c6744799c712fb557d92 languageName: node linkType: hard -"agentkeepalive@npm:^4.2.1": - version: 4.3.0 - resolution: "agentkeepalive@npm:4.3.0" - dependencies: - debug: "npm:^4.1.0" - depd: "npm:^2.0.0" - humanize-ms: "npm:^1.2.1" - checksum: 10/f791317eb4b42278d094547669b9b745e19e5d783bb42a8695820c94098ef18fc99f9d2777b5871cae76d761e45b0add8e6703e044de5d74d47181038ec7b536 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: "npm:^2.0.0" - indent-string: "npm:^4.0.0" - checksum: 10/1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.3 + resolution: "agent-base@npm:7.1.3" + checksum: 10/3db6d8d4651f2aa1a9e4af35b96ab11a7607af57a24f3bc721a387eaa3b5f674e901f0a648b0caefd48f3fd117c7761b79a3b55854e2aebaa96c3f32cf76af84 languageName: node linkType: hard -"ajv@npm:8.11.0": - version: 8.11.0 - resolution: "ajv@npm:8.11.0" +"ajv@npm:8.12.0": + version: 8.12.0 + resolution: "ajv@npm:8.12.0" dependencies: fast-deep-equal: "npm:^3.1.1" json-schema-traverse: "npm:^1.0.0" require-from-string: "npm:^2.0.2" uri-js: "npm:^4.2.2" - checksum: 10/aa0dfd6cebdedde8e77747e84e7b7c55921930974b8547f54b4156164ff70445819398face32dafda4bd4c61bbc7513d308d4c2bf769f8ea6cb9c8449f9faf54 + checksum: 10/b406f3b79b5756ac53bfe2c20852471b08e122bc1ee4cde08ae4d6a800574d9cd78d60c81c69c63ff81e4da7cd0b638fafbb2303ae580d49cf1600b9059efb85 languageName: node linkType: hard -"ajv@npm:^6.10.0, ajv@npm:^6.12.4": - version: 6.12.5 - resolution: "ajv@npm:6.12.5" +"ajv@npm:^6.12.4": + version: 6.12.6 + resolution: "ajv@npm:6.12.6" dependencies: fast-deep-equal: "npm:^3.1.1" fast-json-stable-stringify: "npm:^2.0.0" json-schema-traverse: "npm:^0.4.1" uri-js: "npm:^4.2.2" - checksum: 10/38b579261bd85cff492331c07d488c868fec9f339459b64156dc8401a33be4c6f44655ef54ca7cc4e12cfd74dae0c9d122006ed7d05444defc519030182935f3 + checksum: 10/48d6ad21138d12eb4d16d878d630079a2bda25a04e745c07846a4ad768319533031e28872a9b3c5790fa1ec41aabdf2abed30a56e5a03ebc2cf92184b8ee306c languageName: node linkType: hard @@ -2412,9 +2684,9 @@ __metadata: linkType: hard "ansi-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "ansi-regex@npm:3.0.0" - checksum: 10/2ad11c416f81c39f5c65eafc88cf1d71aa91d76a2f766e75e457c2a3c43e8a003aadbf2966b61c497aa6a6940a36412486c975b3270cdfc3f413b69826189ec3 + version: 3.0.1 + resolution: "ansi-regex@npm:3.0.1" + checksum: 10/09daf180c5f59af9850c7ac1bd7fda85ba596cc8cbeb210826e90755f06c818af86d9fa1e6e8322fab2c3b9e9b03f56c537b42241139f824dd75066a1e7257cc languageName: node linkType: hard @@ -2426,9 +2698,9 @@ __metadata: linkType: hard "ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 10/1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + version: 6.1.0 + resolution: "ansi-regex@npm:6.1.0" + checksum: 10/495834a53b0856c02acd40446f7130cb0f8284f4a39afdab20d5dc42b2e198b1196119fe887beed8f9055c4ff2055e3b2f6d4641d0be018cdfb64fedf6fc1aac languageName: node linkType: hard @@ -2441,13 +2713,12 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^4.1.0": - version: 4.2.1 - resolution: "ansi-styles@npm:4.2.1" +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" dependencies: - "@types/color-name": "npm:^1.1.1" color-convert: "npm:^2.0.1" - checksum: 10/7c74dbc7ec912b9e45dacbfaa7e2513bea6aa24d5357a0cd3255e7f83ecfc62e1454c77ab150a8df60de700c83c17fbbf040e7c204b4b6fc7aa250c8afcb865f + checksum: 10/b4494dfbfc7e4591b4711a396bd27e540f8153914123dccb4cdbbcb514015ada63a3809f362b9d8d4f6b17a706f1d7bea3c6f974b15fa5ae76b5b502070889ff languageName: node linkType: hard @@ -2468,13 +2739,6 @@ __metadata: languageName: node linkType: hard -"aproba@npm:^1.0.3 || ^2.0.0": - version: 2.0.0 - resolution: "aproba@npm:2.0.0" - checksum: 10/c2b9a631298e8d6f3797547e866db642f68493808f5b37cd61da778d5f6ada890d16f668285f7d60bd4fc3b03889bd590ffe62cf81b700e9bb353431238a0a7b - languageName: node - linkType: hard - "arch@npm:^2.2.0": version: 2.2.0 resolution: "arch@npm:2.2.0" @@ -2482,16 +2746,6 @@ __metadata: languageName: node linkType: hard -"are-we-there-yet@npm:^3.0.0": - version: 3.0.1 - resolution: "are-we-there-yet@npm:3.0.1" - dependencies: - delegates: "npm:^1.0.0" - readable-stream: "npm:^3.6.0" - checksum: 10/390731720e1bf9ed5d0efc635ea7df8cbc4c90308b0645a932f06e8495a0bf1ecc7987d3b97e805f62a17d6c4b634074b25200aa4d149be2a7b17250b9744bc4 - languageName: node - linkType: hard - "arg@npm:5.0.2": version: 5.0.2 resolution: "arg@npm:5.0.2" @@ -2527,6 +2781,16 @@ __metadata: languageName: node linkType: hard +"array-buffer-byte-length@npm:^1.0.1, array-buffer-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "array-buffer-byte-length@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + is-array-buffer: "npm:^3.0.5" + checksum: 10/0ae3786195c3211b423e5be8dd93357870e6fb66357d81da968c2c39ef43583ef6eece1f9cb1caccdae4806739c65dea832b44b8593414313cd76a89795fca63 + languageName: node + linkType: hard + "array-flatten@npm:1.1.1": version: 1.1.1 resolution: "array-flatten@npm:1.1.1" @@ -2548,6 +2812,21 @@ __metadata: languageName: node linkType: hard +"arraybuffer.prototype.slice@npm:^1.0.4": + version: 1.0.4 + resolution: "arraybuffer.prototype.slice@npm:1.0.4" + dependencies: + array-buffer-byte-length: "npm:^1.0.1" + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + is-array-buffer: "npm:^3.0.4" + checksum: 10/4821ebdfe7d699f910c7f09bc9fa996f09b96b80bccb4f5dd4b59deae582f6ad6e505ecef6376f8beac1eda06df2dbc89b70e82835d104d6fcabd33c1aed1ae9 + languageName: node + linkType: hard + "assign-symbols@npm:^1.0.0": version: 1.0.0 resolution: "assign-symbols@npm:1.0.0" @@ -2562,6 +2841,13 @@ __metadata: languageName: node linkType: hard +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd + languageName: node + linkType: hard + "atob@npm:^2.1.2": version: 2.1.2 resolution: "atob@npm:2.1.2" @@ -2571,10 +2857,19 @@ __metadata: languageName: node linkType: hard +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: 10/6c9da3a66caddd83c875010a1ca8ef11eac02ba15fb592dc9418b2b5e7b77b645fa7729380a92d9835c2f05f2ca1b6251f39b993e0feb3f1517c74fa1af02cab + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": - version: 1.0.0 - resolution: "balanced-match@npm:1.0.0" - checksum: 10/9b67bfe558772f40cf743a3469b48b286aecec2ea9fe80c48d74845e53aab1cef524fafedf123a63019b49ac397760573ef5f173f539423061f7217cbb5fbd40 + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 10/9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 languageName: node linkType: hard @@ -2616,23 +2911,23 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.1": - version: 1.20.1 - resolution: "body-parser@npm:1.20.1" +"body-parser@npm:1.20.3": + version: 1.20.3 + resolution: "body-parser@npm:1.20.3" dependencies: bytes: "npm:3.1.2" - content-type: "npm:~1.0.4" + content-type: "npm:~1.0.5" debug: "npm:2.6.9" depd: "npm:2.0.0" destroy: "npm:1.2.0" http-errors: "npm:2.0.0" iconv-lite: "npm:0.4.24" on-finished: "npm:2.4.1" - qs: "npm:6.11.0" - raw-body: "npm:2.5.1" + qs: "npm:6.13.0" + raw-body: "npm:2.5.2" type-is: "npm:~1.6.18" unpipe: "npm:1.0.0" - checksum: 10/5f8d128022a2fb8b6e7990d30878a0182f300b70e46b3f9d358a9433ad6275f0de46add6d63206da3637c01c3b38b6111a7480f7e7ac2e9f7b989f6133fe5510 + checksum: 10/8723e3d7a672eb50854327453bed85ac48d045f4958e81e7d470c56bf111f835b97e5b73ae9f6393d0011cc9e252771f46fd281bbabc57d33d3986edf1e6aeca languageName: node linkType: hard @@ -2711,26 +3006,26 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" +"braces@npm:^3.0.3": + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: "npm:^7.0.1" - checksum: 10/966b1fb48d193b9d155f810e5efd1790962f2c4e0829f8440b8ad236ba009222c501f70185ef732fef17a4c490bb33a03b90dab0631feafbdf447da91e8165b1 + fill-range: "npm:^7.1.1" + checksum: 10/fad11a0d4697a27162840b02b1fad249c1683cbc510cd5bf1a471f2f8085c046d41094308c577a50a03a579dd99d5a6b3724c4b5e8b14df2c4443844cfcda2c6 languageName: node linkType: hard -"browserslist@npm:^4.22.2": - version: 4.23.0 - resolution: "browserslist@npm:4.23.0" +"browserslist@npm:^4.24.0": + version: 4.24.5 + resolution: "browserslist@npm:4.24.5" dependencies: - caniuse-lite: "npm:^1.0.30001587" - electron-to-chromium: "npm:^1.4.668" - node-releases: "npm:^2.0.14" - update-browserslist-db: "npm:^1.0.13" + caniuse-lite: "npm:^1.0.30001716" + electron-to-chromium: "npm:^1.5.149" + node-releases: "npm:^2.0.19" + update-browserslist-db: "npm:^1.1.3" bin: browserslist: cli.js - checksum: 10/496c3862df74565dd942b4ae65f502c575cbeba1fa4a3894dad7aa3b16130dc3033bc502d8848147f7b625154a284708253d9598bcdbef5a1e34cf11dc7bad8e + checksum: 10/93fde829b77f20e2c4e1e0eaed154681c05e4828420e4afba790d480daa5de742977a44bbac8567881b8fbec3da3dea7ca1cb578ac1fd4385ef4ae91ca691d64 languageName: node linkType: hard @@ -2743,10 +3038,10 @@ __metadata: languageName: node linkType: hard -"bson@npm:^5.3.0": - version: 5.3.0 - resolution: "bson@npm:5.3.0" - checksum: 10/491172c38ff11fd321471757fc57676f4ec3608ff0f0d148601d59c61b491ab282844bbfcbaaca1a3669e9ab8055255677d96579c3574cb8a19bce7dcdfde214 +"bson@npm:^6.10.3": + version: 6.10.3 + resolution: "bson@npm:6.10.3" + checksum: 10/53693ad7636fa1a128f32d5c30a9584b4a09a2b2aa2040ea8bf8dca35a283eb1394138770bc6c2dae91b0c6df96b3caef3b14532644736f4d7a1d3177969537b languageName: node linkType: hard @@ -2774,29 +3069,23 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^16.1.0": - version: 16.1.3 - resolution: "cacache@npm:16.1.3" +"cacache@npm:^19.0.1": + version: 19.0.1 + resolution: "cacache@npm:19.0.1" dependencies: - "@npmcli/fs": "npm:^2.1.0" - "@npmcli/move-file": "npm:^2.0.0" - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.1.0" - glob: "npm:^8.0.1" - infer-owner: "npm:^1.0.4" - lru-cache: "npm:^7.7.1" - minipass: "npm:^3.1.6" - minipass-collect: "npm:^1.0.2" + "@npmcli/fs": "npm:^4.0.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - mkdirp: "npm:^1.0.4" - p-map: "npm:^4.0.0" - promise-inflight: "npm:^1.0.1" - rimraf: "npm:^3.0.2" - ssri: "npm:^9.0.0" - tar: "npm:^6.1.11" - unique-filename: "npm:^2.0.0" - checksum: 10/a14524d90e377ee691d63a81173b33c473f8bc66eb299c64290b58e1d41b28842397f8d6c15a01b4c57ca340afcec019ae112a45c2f67a79f76130d326472e92 + p-map: "npm:^7.0.2" + ssri: "npm:^12.0.0" + tar: "npm:^7.4.3" + unique-filename: "npm:^4.0.0" + checksum: 10/ea026b27b13656330c2bbaa462a88181dcaa0435c1c2e705db89b31d9bdf7126049d6d0445ba746dca21454a0cfdf1d6f47fd39d34c8c8435296b30bc5738a13 languageName: node linkType: hard @@ -2817,13 +3106,35 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.0": +"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": version: 1.0.2 - resolution: "call-bind@npm:1.0.2" + resolution: "call-bind-apply-helpers@npm:1.0.2" + dependencies: + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + checksum: 10/00482c1f6aa7cfb30fb1dbeb13873edf81cfac7c29ed67a5957d60635a56b2a4a480f1016ddbdb3395cc37900d46037fb965043a51c5c789ffeab4fc535d18b5 + languageName: node + linkType: hard + +"call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": + version: 1.0.8 + resolution: "call-bind@npm:1.0.8" + dependencies: + call-bind-apply-helpers: "npm:^1.0.0" + es-define-property: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" + set-function-length: "npm:^1.2.2" + checksum: 10/659b03c79bbfccf0cde3a79e7d52570724d7290209823e1ca5088f94b52192dc1836b82a324d0144612f816abb2f1734447438e38d9dafe0b3f82c2a1b9e3bce + languageName: node + linkType: hard + +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3, call-bound@npm:^1.0.4": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" dependencies: - function-bind: "npm:^1.1.1" - get-intrinsic: "npm:^1.0.2" - checksum: 10/ca787179c1cbe09e1697b56ad499fd05dc0ae6febe5081d728176ade699ea6b1589240cb1ff1fe11fcf9f61538c1af60ad37e8eb2ceb4ef21cd6085dfd3ccedd + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10/ef2b96e126ec0e58a7ff694db43f4d0d44f80e641370c21549ed911fecbdbc2df3ebc9bddad918d6bbdefeafb60bb3337902006d5176d72bcd2da74820991af7 languageName: node linkType: hard @@ -2848,10 +3159,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001587": - version: 1.0.30001599 - resolution: "caniuse-lite@npm:1.0.30001599" - checksum: 10/c9a5ad806fc0d446e4f995d551b840d8fdcbe97958b7f83ff7a255a8ef5e40ca12ca1a508c66b3ab147e19eef932d28772d205c046500dd0740ea9dfb602e2e1 +"caniuse-lite@npm:^1.0.30001716": + version: 1.0.30001718 + resolution: "caniuse-lite@npm:1.0.30001718" + checksum: 10/e172a4c156f743cc947e659f353ad9edb045725cc109a02cc792dcbf98569356ebfa4bb4356e3febf87427aab0951c34c1ee5630629334f25ae6f76de7d86fd0 languageName: node linkType: hard @@ -2878,7 +3189,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.1, chalk@npm:^2.4.1, chalk@npm:^2.4.2": +"chalk@npm:^2.0.1, chalk@npm:^2.4.1": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -2889,17 +3200,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0": - version: 4.1.0 - resolution: "chalk@npm:4.1.0" - dependencies: - ansi-styles: "npm:^4.1.0" - supports-color: "npm:^7.1.0" - checksum: 10/e8d2b9b9abe5aee78caae44e2fd86ade56e440df5822006d702ce18771c00418b6f2c0eb294093d5486b852c83f021e409205d0ee07095fb14f5c8f9db9e7f80 - languageName: node - linkType: hard - -"chalk@npm:^4.1.2": +"chalk@npm:^4.0.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -2910,9 +3211,9 @@ __metadata: linkType: hard "chalk@npm:^5.0.1": - version: 5.3.0 - resolution: "chalk@npm:5.3.0" - checksum: 10/6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea + version: 5.4.1 + resolution: "chalk@npm:5.4.1" + checksum: 10/29df3ffcdf25656fed6e95962e2ef86d14dfe03cd50e7074b06bad9ffbbf6089adbb40f75c00744d843685c8d008adaf3aed31476780312553caf07fa86e5bc7 languageName: node linkType: hard @@ -2939,10 +3240,10 @@ __metadata: languageName: node linkType: hard -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: 10/c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10/b63cb1f73d171d140a2ed8154ee6566c8ab775d3196b0e03a2a94b5f6a0ce7777ee5685ca56849403c8d17bd457a6540672f9a60696a6137c7a409097495b82c languageName: node linkType: hard @@ -2965,13 +3266,6 @@ __metadata: languageName: node linkType: hard -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 10/2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 - languageName: node - linkType: hard - "cli-boxes@npm:^1.0.0": version: 1.0.0 resolution: "cli-boxes@npm:1.0.0" @@ -3039,19 +3333,10 @@ __metadata: languageName: node linkType: hard -"color-support@npm:^1.1.3": - version: 1.1.3 - resolution: "color-support@npm:1.1.3" - bin: - color-support: bin.js - checksum: 10/4bcfe30eea1498fe1cabc852bbda6c9770f230ea0e4faf4611c5858b1b9e4dde3730ac485e65f54ca182f4c50b626c1bea7c8441ceda47367a54a818c248aa7a - languageName: node - linkType: hard - "component-emitter@npm:^1.2.1": - version: 1.3.0 - resolution: "component-emitter@npm:1.3.0" - checksum: 10/dfc1ec2e7aa2486346c068f8d764e3eefe2e1ca0b24f57506cd93b2ae3d67829a7ebd7cc16e2bf51368fac2f45f78fcff231718e40b1975647e4a86be65e1d05 + version: 1.3.1 + resolution: "component-emitter@npm:1.3.1" + checksum: 10/94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d languageName: node linkType: hard @@ -3100,13 +3385,6 @@ __metadata: languageName: node linkType: hard -"console-control-strings@npm:^1.1.0": - version: 1.1.0 - resolution: "console-control-strings@npm:1.1.0" - checksum: 10/27b5fa302bc8e9ae9e98c03c66d76ca289ad0c61ce2fe20ab288d288bee875d217512d2edb2363fc83165e88f1c405180cf3f5413a46e51b4fe1a004840c6cdb - languageName: node - linkType: hard - "content-disposition@npm:0.5.2": version: 0.5.2 resolution: "content-disposition@npm:0.5.2" @@ -3123,7 +3401,7 @@ __metadata: languageName: node linkType: hard -"content-type@npm:~1.0.4": +"content-type@npm:~1.0.4, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" checksum: 10/585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662 @@ -3144,10 +3422,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0": - version: 0.5.0 - resolution: "cookie@npm:0.5.0" - checksum: 10/aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 +"cookie@npm:0.7.1": + version: 0.7.1 + resolution: "cookie@npm:0.7.1" + checksum: 10/aec6a6aa0781761bf55d60447d6be08861d381136a0fe94aa084fddd4f0300faa2b064df490c6798adfa1ebaef9e0af9b08a189c823e0811b8b313b3d9a03380 languageName: node linkType: hard @@ -3196,26 +3474,26 @@ __metadata: linkType: hard "cross-spawn@npm:^6.0.5": - version: 6.0.5 - resolution: "cross-spawn@npm:6.0.5" + version: 6.0.6 + resolution: "cross-spawn@npm:6.0.6" dependencies: nice-try: "npm:^1.0.4" path-key: "npm:^2.0.1" semver: "npm:^5.5.0" shebang-command: "npm:^1.2.0" which: "npm:^1.2.9" - checksum: 10/f07e643b4875f26adffcd7f13bc68d9dff20cf395f8ed6f43a23f3ee24fc3a80a870a32b246fd074e514c8fd7da5f978ac6a7668346eec57aa87bac89c1ed3a1 + checksum: 10/7abf6137b23293103a22bfeaf320f2d63faae70d97ddb4b58597237501d2efdd84cdc69a30246977e0c5f68216593894d41a7f122915dd4edf448db14c74171b languageName: node linkType: hard -"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" +"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" dependencies: path-key: "npm:^3.1.0" shebang-command: "npm:^2.0.0" which: "npm:^2.0.1" - checksum: 10/e1a13869d2f57d974de0d9ef7acbf69dc6937db20b918525a01dacb5032129bd552d290d886d981e99f1b624cb03657084cc87bd40f115c07ecf376821c729ce + checksum: 10/0d52657d7ae36eb130999dffff1168ec348687b48dd38e2ff59992ed916c88d328cf1d07ff4a4a10bc78de5e1c23f04b306d569e42f7a2293915c081e4dfee86 languageName: node linkType: hard @@ -3226,10 +3504,43 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2": - version: 3.1.3 - resolution: "csstype@npm:3.1.3" - checksum: 10/f593cce41ff5ade23f44e77521e3a1bcc2c64107041e1bf6c3c32adc5187d0d60983292fda326154d20b01079e24931aa5b08e4467cc488b60bb1e7f6d478ade +"csstype@npm:^3.0.2": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 10/f593cce41ff5ade23f44e77521e3a1bcc2c64107041e1bf6c3c32adc5187d0d60983292fda326154d20b01079e24931aa5b08e4467cc488b60bb1e7f6d478ade + languageName: node + linkType: hard + +"data-view-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-buffer@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.2" + checksum: 10/c10b155a4e93999d3a215d08c23eea95f865e1f510b2e7748fcae1882b776df1afe8c99f483ace7fc0e5a3193ab08da138abebc9829d12003746c5a338c4d644 + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-byte-length@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.2" + checksum: 10/2a47055fcf1ab3ec41b00b6f738c6461a841391a643c9ed9befec1117c1765b4d492661d97fb7cc899200c328949dca6ff189d2c6537d96d60e8a02dfe3c95f7 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-offset@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + is-data-view: "npm:^1.0.1" + checksum: 10/fa3bdfa0968bea6711ee50375094b39f561bce3f15f9e558df59de9c25f0bdd4cddc002d9c1d70ac7772ebd36854a7e22d1761e7302a934e6f1c2263bcf44aa2 languageName: node linkType: hard @@ -3242,15 +3553,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": + version: 4.4.1 + resolution: "debug@npm:4.4.1" dependencies: - ms: "npm:2.1.2" + ms: "npm:^2.1.3" peerDependenciesMeta: supports-color: optional: true - checksum: 10/0073c3bcbd9cb7d71dd5f6b55be8701af42df3e56e911186dfa46fac3a5b9eb7ce7f377dd1d3be6db8977221f8eb333d945216f645cf56f6b688cd484837d255 + checksum: 10/8e2709b2144f03c7950f8804d01ccb3786373df01e406a0f66928e47001cf2d336cbed9ee137261d4f90d68d8679468c755e3548ed83ddacdc82b194d2468afe languageName: node linkType: hard @@ -3263,18 +3574,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.1.1": - version: 4.2.0 - resolution: "debug@npm:4.2.0" - dependencies: - ms: "npm:2.1.2" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10/4877714f15003830eed9f4a71c2ee3eb6032807b5f31638ec5069280f8d6f5719b75f95308bb51361b32799f14d95494940f7ba21c81a731e4394af700012a1a - languageName: node - linkType: hard - "decode-uri-component@npm:^0.2.0": version: 0.2.2 resolution: "decode-uri-component@npm:0.2.2" @@ -3290,18 +3589,31 @@ __metadata: linkType: hard "deep-is@npm:^0.1.3": - version: 0.1.3 - resolution: "deep-is@npm:0.1.3" - checksum: 10/dee1094e987a784a9a9c8549fc65eeca3422aef3bf2f9579f76c126085f280311d09273826c2f430d84fd09d64f6a578e5e7a4ac6ba1d50ea6cff0ddf605c025 + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: 10/ec12d074aef5ae5e81fa470b9317c313142c9e8e2afe3f8efa124db309720db96d1d222b82b84c834e5f87e7a614b44a4684b6683583118b87c833b3be40d4d8 languageName: node linkType: hard -"define-properties@npm:^1.1.2, define-properties@npm:^1.1.3": - version: 1.1.3 - resolution: "define-properties@npm:1.1.3" +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" + dependencies: + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.0.1" + checksum: 10/abdcb2505d80a53524ba871273e5da75e77e52af9e15b3aa65d8aad82b8a3a424dad7aee2cc0b71470ac7acf501e08defac362e8b6a73cdb4309f028061df4ae + languageName: node + linkType: hard + +"define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" dependencies: - object-keys: "npm:^1.0.12" - checksum: 10/33125cafaf4de2c9934cfba20e0a45bccc53fa6d85370a48c0b5a9a0c76c7d0497a5fdf01bc5c1186cb61f2747f19f43520ca6fdd37b4d0290f552c6747e0a17 + define-data-property: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.0" + object-keys: "npm:^1.1.1" + checksum: 10/b4ccd00597dd46cb2d4a379398f5b19fca84a16f3374e2249201992f36b30f6835949a9429669ee6b41b6e837205a163eadd745e472069e70dfc10f03e5fcc12 languageName: node linkType: hard @@ -3333,14 +3645,7 @@ __metadata: languageName: node linkType: hard -"delegates@npm:^1.0.0": - version: 1.0.0 - resolution: "delegates@npm:1.0.0" - checksum: 10/a51744d9b53c164ba9c0492471a1a2ffa0b6727451bdc89e31627fdf4adda9d51277cfcbfb20f0a6f08ccb3c436f341df3e92631a3440226d93a8971724771fd - languageName: node - linkType: hard - -"depd@npm:2.0.0, depd@npm:^2.0.0": +"depd@npm:2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" checksum: 10/c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca @@ -3354,6 +3659,13 @@ __metadata: languageName: node linkType: hard +"detect-libc@npm:^2.0.3, detect-libc@npm:^2.0.4": + version: 2.0.4 + resolution: "detect-libc@npm:2.0.4" + checksum: 10/136e995f8c5ffbc515955b0175d441b967defd3d5f2268e89fa695e9c7170d8bed17993e31a34b04f0fad33d844a3a598e0fd519a8e9be3cad5f67662d96fee0 + languageName: node + linkType: hard + "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -3382,9 +3694,20 @@ __metadata: linkType: hard "dotenv@npm:^16.1.4": - version: 16.1.4 - resolution: "dotenv@npm:16.1.4" - checksum: 10/b0caa00283490d1cdb6ad892fcdbc86a6f5e3e0fb5e8da32e599fb3f9fa778095812ae1b936761090416b355fe8724cb47624333a7bd770bb9c667f7d186d8a0 + version: 16.5.0 + resolution: "dotenv@npm:16.5.0" + checksum: 10/e68a16834f1a41cc2dfb01563bc150668ad675e6cd09191211467b5c0806b6ecd6ec438e021aa8e01cd0e72d2b70ef4302bec7cc0fe15b6955f85230b62dc8a9 + languageName: node + linkType: hard + +"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "dunder-proto@npm:1.0.1" + dependencies: + call-bind-apply-helpers: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.2.0" + checksum: 10/5add88a3d68d42d6e6130a0cac450b7c2edbe73364bbd2fc334564418569bea97c6943a8fcd70e27130bf32afc236f30982fc4905039b703f23e9e0433c29934 languageName: node linkType: hard @@ -3409,10 +3732,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.668": - version: 1.4.711 - resolution: "electron-to-chromium@npm:1.4.711" - checksum: 10/48ae0e074d4c2fe4594aded24547c31ee010732a40a970751b4205dc2397f2ceeaafcded9fa03079d0453cc514a0d72ff38992235328d056bd266722452a4e13 +"electron-to-chromium@npm:^1.5.149": + version: 1.5.157 + resolution: "electron-to-chromium@npm:1.5.157" + checksum: 10/806cbb515f17d6599369d184032f21b5cc2bf4194267c08a5b134eb9a6c2fc291c87acda5c0baccd6f3833fb543b74b7edc5767d5594dec92c626a153797e7cf languageName: node linkType: hard @@ -3437,6 +3760,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:~2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: 10/abf5cd51b78082cf8af7be6785813c33b6df2068ce5191a40ca8b1afe6a86f9230af9a9ce694a5ce4665955e5c1120871826df9c128a642e09c58d592e2807fe + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -3446,6 +3776,16 @@ __metadata: languageName: node linkType: hard +"enhanced-resolve@npm:^5.18.1": + version: 5.18.1 + resolution: "enhanced-resolve@npm:5.18.1" + dependencies: + graceful-fs: "npm:^4.2.4" + tapable: "npm:^2.2.0" + checksum: 10/50e81c7fe2239fba5670ebce78a34709906ed3a79274aa416434f7307b252e0b7824d76a7dd403eca795571dc6afd9a44183fc45a68475e8f2fdfbae6e92fcc3 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -3469,63 +3809,138 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.0-next.1, es-abstract@npm:^1.17.5": - version: 1.17.6 - resolution: "es-abstract@npm:1.17.6" - dependencies: - es-to-primitive: "npm:^1.2.1" - function-bind: "npm:^1.1.1" - has: "npm:^1.0.3" - has-symbols: "npm:^1.0.1" - is-callable: "npm:^1.2.0" - is-regex: "npm:^1.1.0" - object-inspect: "npm:^1.7.0" +"es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.9": + version: 1.23.10 + resolution: "es-abstract@npm:1.23.10" + dependencies: + array-buffer-byte-length: "npm:^1.0.2" + arraybuffer.prototype.slice: "npm:^1.0.4" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + data-view-buffer: "npm:^1.0.2" + data-view-byte-length: "npm:^1.0.2" + data-view-byte-offset: "npm:^1.0.1" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + es-set-tostringtag: "npm:^2.1.0" + es-to-primitive: "npm:^1.3.0" + function.prototype.name: "npm:^1.1.8" + get-intrinsic: "npm:^1.3.0" + get-proto: "npm:^1.0.1" + get-symbol-description: "npm:^1.1.0" + globalthis: "npm:^1.0.4" + gopd: "npm:^1.2.0" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + internal-slot: "npm:^1.1.0" + is-array-buffer: "npm:^3.0.5" + is-callable: "npm:^1.2.7" + is-data-view: "npm:^1.0.2" + is-regex: "npm:^1.2.1" + is-shared-array-buffer: "npm:^1.0.4" + is-string: "npm:^1.1.1" + is-typed-array: "npm:^1.1.15" + is-weakref: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + object-inspect: "npm:^1.13.4" object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.0" - string.prototype.trimend: "npm:^1.0.1" - string.prototype.trimstart: "npm:^1.0.1" - checksum: 10/70c5b7feed56e9ffc0d9ce3b37c89bfd29d523227aa75b421bba392b3c34190337df779770f3ede6ac7a8c779d01a5bbdbda4979cc1347bd56e100ae03bdf248 + object.assign: "npm:^4.1.7" + own-keys: "npm:^1.0.1" + regexp.prototype.flags: "npm:^1.5.4" + safe-array-concat: "npm:^1.1.3" + safe-push-apply: "npm:^1.0.0" + safe-regex-test: "npm:^1.1.0" + set-proto: "npm:^1.0.0" + string.prototype.trim: "npm:^1.2.10" + string.prototype.trimend: "npm:^1.0.9" + string.prototype.trimstart: "npm:^1.0.8" + typed-array-buffer: "npm:^1.0.3" + typed-array-byte-length: "npm:^1.0.3" + typed-array-byte-offset: "npm:^1.0.4" + typed-array-length: "npm:^1.0.7" + unbox-primitive: "npm:^1.1.0" + which-typed-array: "npm:^1.1.19" + checksum: 10/d3b6d560fa5eb6f3b4da4d4031d0a9455a7ec18f64ae0698831c0ce13d241f074a40e9711be3eb5f50c5844dde6070439ccfd6ce789a12bc9676e76379616d0c + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1": + version: 1.0.1 + resolution: "es-define-property@npm:1.0.1" + checksum: 10/f8dc9e660d90919f11084db0a893128f3592b781ce967e4fccfb8f3106cb83e400a4032c559184ec52ee1dbd4b01e7776c7cd0b3327b1961b1a4a7008920fe78 languageName: node linkType: hard -"es-to-primitive@npm:^1.2.1": - version: 1.2.1 - resolution: "es-to-primitive@npm:1.2.1" - dependencies: - is-callable: "npm:^1.1.4" - is-date-object: "npm:^1.0.1" - is-symbol: "npm:^1.0.2" - checksum: 10/74aeeefe2714cf99bb40cab7ce3012d74e1e2c1bd60d0a913b467b269edde6e176ca644b5ba03a5b865fb044a29bca05671cd445c85ca2cdc2de155d7fc8fe9b - languageName: node - linkType: hard - -"esbuild@npm:^0.19.3": - version: 0.19.12 - resolution: "esbuild@npm:0.19.12" - dependencies: - "@esbuild/aix-ppc64": "npm:0.19.12" - "@esbuild/android-arm": "npm:0.19.12" - "@esbuild/android-arm64": "npm:0.19.12" - "@esbuild/android-x64": "npm:0.19.12" - "@esbuild/darwin-arm64": "npm:0.19.12" - "@esbuild/darwin-x64": "npm:0.19.12" - "@esbuild/freebsd-arm64": "npm:0.19.12" - "@esbuild/freebsd-x64": "npm:0.19.12" - "@esbuild/linux-arm": "npm:0.19.12" - "@esbuild/linux-arm64": "npm:0.19.12" - "@esbuild/linux-ia32": "npm:0.19.12" - "@esbuild/linux-loong64": "npm:0.19.12" - "@esbuild/linux-mips64el": "npm:0.19.12" - "@esbuild/linux-ppc64": "npm:0.19.12" - "@esbuild/linux-riscv64": "npm:0.19.12" - "@esbuild/linux-s390x": "npm:0.19.12" - "@esbuild/linux-x64": "npm:0.19.12" - "@esbuild/netbsd-x64": "npm:0.19.12" - "@esbuild/openbsd-x64": "npm:0.19.12" - "@esbuild/sunos-x64": "npm:0.19.12" - "@esbuild/win32-arm64": "npm:0.19.12" - "@esbuild/win32-ia32": "npm:0.19.12" - "@esbuild/win32-x64": "npm:0.19.12" +"es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 10/96e65d640156f91b707517e8cdc454dd7d47c32833aa3e85d79f24f9eb7ea85f39b63e36216ef0114996581969b59fe609a94e30316b08f5f4df1d44134cf8d5 + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 10/54fe77de288451dae51c37bfbfe3ec86732dc3778f98f3eb3bdb4bf48063b2c0b8f9c93542656986149d08aa5be3204286e2276053d19582b76753f1a2728867 + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" + dependencies: + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10/86814bf8afbcd8966653f731415888019d4bc4aca6b6c354132a7a75bb87566751e320369654a101d23a91c87a85c79b178bcf40332839bd347aff437c4fb65f + languageName: node + linkType: hard + +"es-to-primitive@npm:^1.3.0": + version: 1.3.0 + resolution: "es-to-primitive@npm:1.3.0" + dependencies: + is-callable: "npm:^1.2.7" + is-date-object: "npm:^1.0.5" + is-symbol: "npm:^1.0.4" + checksum: 10/17faf35c221aad59a16286cbf58ef6f080bf3c485dff202c490d074d8e74da07884e29b852c245d894eac84f73c58330ec956dfd6d02c0b449d75eb1012a3f9b + languageName: node + linkType: hard + +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.21.5" + "@esbuild/android-arm": "npm:0.21.5" + "@esbuild/android-arm64": "npm:0.21.5" + "@esbuild/android-x64": "npm:0.21.5" + "@esbuild/darwin-arm64": "npm:0.21.5" + "@esbuild/darwin-x64": "npm:0.21.5" + "@esbuild/freebsd-arm64": "npm:0.21.5" + "@esbuild/freebsd-x64": "npm:0.21.5" + "@esbuild/linux-arm": "npm:0.21.5" + "@esbuild/linux-arm64": "npm:0.21.5" + "@esbuild/linux-ia32": "npm:0.21.5" + "@esbuild/linux-loong64": "npm:0.21.5" + "@esbuild/linux-mips64el": "npm:0.21.5" + "@esbuild/linux-ppc64": "npm:0.21.5" + "@esbuild/linux-riscv64": "npm:0.21.5" + "@esbuild/linux-s390x": "npm:0.21.5" + "@esbuild/linux-x64": "npm:0.21.5" + "@esbuild/netbsd-x64": "npm:0.21.5" + "@esbuild/openbsd-x64": "npm:0.21.5" + "@esbuild/sunos-x64": "npm:0.21.5" + "@esbuild/win32-arm64": "npm:0.21.5" + "@esbuild/win32-ia32": "npm:0.21.5" + "@esbuild/win32-x64": "npm:0.21.5" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -3575,14 +3990,14 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10/861fa8eb2428e8d6521a4b7c7930139e3f45e8d51a86985cc29408172a41f6b18df7b3401e7e5e2d528cdf83742da601ddfdc77043ddc4f1c715a8ddb2d8a255 + checksum: 10/d2ff2ca84d30cce8e871517374d6c2290835380dc7cd413b2d49189ed170d45e407be14de2cb4794cf76f75cf89955c4714726ebd3de7444b3046f5cab23ab6b languageName: node linkType: hard -"escalade@npm:^3.1.1": - version: 3.1.2 - resolution: "escalade@npm:3.1.2" - checksum: 10/a1e07fea2f15663c30e40b9193d658397846ffe28ce0a3e4da0d8e485fedfeca228ab846aee101a05015829adf39f9934ff45b2a3fca47bed37a29646bd05cd3 +"escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10/9d7169e3965b2f9ae46971afa392f6e5a25545ea30f2e2dd99c9b0a95a3f52b5653681a84f5b2911a413ddad2d7a93d3514165072f349b5ffc59c75a899970d6 languageName: node linkType: hard @@ -3608,13 +4023,13 @@ __metadata: linkType: hard "eslint-config-prettier@npm:^8.6.0": - version: 8.8.0 - resolution: "eslint-config-prettier@npm:8.8.0" + version: 8.10.0 + resolution: "eslint-config-prettier@npm:8.10.0" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 10/3638144cecada897105ff9442bc85aba71c4f44d7d25b576cb34d50a207f6655f7cc55e729aad1a934a9f15e55c88e7adcbd1067d6582325fc89864c879b52f1 + checksum: 10/0a51ab1417cbf80fabcf7a406960a142663539c8140fdb0a187b78f3d708b9d137a62a4bc4e689150e290b667750ddabd1740a516623b0cb4adb6cc1962cfe2c languageName: node linkType: hard @@ -3643,43 +4058,44 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.0": - version: 7.2.0 - resolution: "eslint-scope@npm:7.2.0" +"eslint-scope@npm:^7.2.2": + version: 7.2.2 + resolution: "eslint-scope@npm:7.2.2" dependencies: esrecurse: "npm:^4.3.0" estraverse: "npm:^5.2.0" - checksum: 10/94d8942840b35bf5e6559bd0f0a8b10610d65b1e44e41295e66ed1fe82f83bc51756e7af607d611b75f435adf821122bd901aa565701596ca1a628db41c0cd87 + checksum: 10/5c660fb905d5883ad018a6fea2b49f3cb5b1cbf2cd4bd08e98646e9864f9bc2c74c0839bed2d292e90a4a328833accc197c8f0baed89cbe8d605d6f918465491 languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1": - version: 3.4.1 - resolution: "eslint-visitor-keys@npm:3.4.1" - checksum: 10/92641e7ccde470065aa2931161a6a053690a54aae35ae08f38e376ecfd7c012573c542b37a3baecf921eb951fd57943411392f464c2b8f3399adee4723a1369f +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 10/3f357c554a9ea794b094a09bd4187e5eacd1bc0d0653c3adeb87962c548e6a1ab8f982b86963ae1337f5d976004146536dcee5d0e2806665b193fbfbf1a9231b languageName: node linkType: hard "eslint@npm:^8.42.0": - version: 8.42.0 - resolution: "eslint@npm:8.42.0" + version: 8.57.1 + resolution: "eslint@npm:8.57.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.4.0" - "@eslint/eslintrc": "npm:^2.0.3" - "@eslint/js": "npm:8.42.0" - "@humanwhocodes/config-array": "npm:^0.11.10" + "@eslint-community/regexpp": "npm:^4.6.1" + "@eslint/eslintrc": "npm:^2.1.4" + "@eslint/js": "npm:8.57.1" + "@humanwhocodes/config-array": "npm:^0.13.0" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" - ajv: "npm:^6.10.0" + "@ungap/structured-clone": "npm:^1.2.0" + ajv: "npm:^6.12.4" chalk: "npm:^4.0.0" cross-spawn: "npm:^7.0.2" debug: "npm:^4.3.2" doctrine: "npm:^3.0.0" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.0" - eslint-visitor-keys: "npm:^3.4.1" - espree: "npm:^9.5.2" + eslint-scope: "npm:^7.2.2" + eslint-visitor-keys: "npm:^3.4.3" + espree: "npm:^9.6.1" esquery: "npm:^1.4.2" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" @@ -3689,7 +4105,6 @@ __metadata: globals: "npm:^13.19.0" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.0" - import-fresh: "npm:^3.0.0" imurmurhash: "npm:^0.1.4" is-glob: "npm:^4.0.0" is-path-inside: "npm:^3.0.3" @@ -3699,33 +4114,32 @@ __metadata: lodash.merge: "npm:^4.6.2" minimatch: "npm:^3.1.2" natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.1" + optionator: "npm:^0.9.3" strip-ansi: "npm:^6.0.1" - strip-json-comments: "npm:^3.1.0" text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 10/189ba2ae856703c187deef590fa2cee70f294a381837e6acf0fdd9a715235bc91381c62d8ccc891de09155e950d1bd9495c9b18019053fdde7db0a39938b2934 + checksum: 10/5504fa24879afdd9f9929b2fbfc2ee9b9441a3d464efd9790fbda5f05738858530182029f13323add68d19fec749d3ab4a70320ded091ca4432b1e9cc4ed104c languageName: node linkType: hard -"espree@npm:^9.5.2": - version: 9.5.2 - resolution: "espree@npm:9.5.2" +"espree@npm:^9.6.0, espree@npm:^9.6.1": + version: 9.6.1 + resolution: "espree@npm:9.6.1" dependencies: - acorn: "npm:^8.8.0" + acorn: "npm:^8.9.0" acorn-jsx: "npm:^5.3.2" eslint-visitor-keys: "npm:^3.4.1" - checksum: 10/2c9d0fec9ac1230856baec338bd238ca9a69b451ee451f0da25e07d356e1bdef45a2ae5f8c374f492f4bb568d17fc7c998ef44f04a2e9b6a11fc8c194c677ba4 + checksum: 10/255ab260f0d711a54096bdeda93adff0eadf02a6f9b92f02b323e83a2b7fc258797919437ad331efec3930475feb0142c5ecaaf3cdab4befebd336d47d3f3134 languageName: node linkType: hard "esquery@npm:^1.4.2": - version: 1.5.0 - resolution: "esquery@npm:1.5.0" + version: 1.6.0 + resolution: "esquery@npm:1.6.0" dependencies: estraverse: "npm:^5.1.0" - checksum: 10/e65fcdfc1e0ff5effbf50fb4f31ea20143ae5df92bb2e4953653d8d40aa4bc148e0d06117a592ce4ea53eeab1dafdfded7ea7e22a5be87e82d73757329a1b01d + checksum: 10/c587fb8ec9ed83f2b1bc97cf2f6854cc30bf784a79d62ba08c6e358bf22280d69aee12827521cf38e69ae9761d23fb7fde593ce315610f85655c139d99b05e5a languageName: node linkType: hard @@ -3746,9 +4160,9 @@ __metadata: linkType: hard "estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": - version: 5.2.0 - resolution: "estraverse@npm:5.2.0" - checksum: 10/9740a8fa4257682c1d6c14a0befc884af31e76013a97c647aed21aeb1766270e153e34cc06ab8d354a377bb6ed6b785b1f5deb1228ceb7e3792bf88fb79b2ce8 + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 10/37cbe6e9a68014d34dbdc039f90d0baf72436809d02edffcc06ba3c2a12eb298048f877511353b130153e532aac8d68ba78430c0dd2f44806ebc7c014b01585e languageName: node linkType: hard @@ -3813,42 +4227,49 @@ __metadata: languageName: node linkType: hard +"exponential-backoff@npm:^3.1.1": + version: 3.1.2 + resolution: "exponential-backoff@npm:3.1.2" + checksum: 10/ca2f01f1aa4dafd3f3917bd531ab5be08c6f5f4b2389d2e974f903de3cbeb50b9633374353516b6afd70905775e33aba11afab1232d3acf0aa2963b98a611c51 + languageName: node + linkType: hard + "express@npm:^4.18.1": - version: 4.18.2 - resolution: "express@npm:4.18.2" + version: 4.21.2 + resolution: "express@npm:4.21.2" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" - body-parser: "npm:1.20.1" + body-parser: "npm:1.20.3" content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" - cookie: "npm:0.5.0" + cookie: "npm:0.7.1" cookie-signature: "npm:1.0.6" debug: "npm:2.6.9" depd: "npm:2.0.0" - encodeurl: "npm:~1.0.2" + encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" etag: "npm:~1.8.1" - finalhandler: "npm:1.2.0" + finalhandler: "npm:1.3.1" fresh: "npm:0.5.2" http-errors: "npm:2.0.0" - merge-descriptors: "npm:1.0.1" + merge-descriptors: "npm:1.0.3" methods: "npm:~1.1.2" on-finished: "npm:2.4.1" parseurl: "npm:~1.3.3" - path-to-regexp: "npm:0.1.7" + path-to-regexp: "npm:0.1.12" proxy-addr: "npm:~2.0.7" - qs: "npm:6.11.0" + qs: "npm:6.13.0" range-parser: "npm:~1.2.1" safe-buffer: "npm:5.2.1" - send: "npm:0.18.0" - serve-static: "npm:1.15.0" + send: "npm:0.19.0" + serve-static: "npm:1.16.2" setprototypeof: "npm:1.2.0" statuses: "npm:2.0.1" type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 10/869ae89ed6ff4bed7b373079dc58e5dddcf2915a2669b36037ff78c99d675ae930e5fe052b35c24f56557d28a023bb1cbe3e2f2fb87eaab96a1cedd7e597809d + checksum: 10/34571c442fc8c9f2c4b442d2faa10ea1175cf8559237fc6a278f5ce6254a8ffdbeb9a15d99f77c1a9f2926ab183e3b7ba560e3261f1ad4149799e3412ab66bd1 languageName: node linkType: hard @@ -3902,15 +4323,15 @@ __metadata: linkType: hard "fast-glob@npm:^3.2.9": - version: 3.2.12 - resolution: "fast-glob@npm:3.2.12" + version: 3.3.3 + resolution: "fast-glob@npm:3.3.3" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 10/641e748664ae0fdc4dadd23c812fd7d6c80cd92d451571cb1f81fa87edb750e917f25abf74fc9503c97438b0b67ecf75b738bb8e50a83b16bd2a88b4d64e81fa + micromatch: "npm:^4.0.8" + checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad languageName: node linkType: hard @@ -3928,32 +4349,35 @@ __metadata: languageName: node linkType: hard -"fast-url-parser@npm:1.1.3": - version: 1.1.3 - resolution: "fast-url-parser@npm:1.1.3" - dependencies: - punycode: "npm:^1.3.2" - checksum: 10/6d33f46ce9776f7f3017576926207a950ca39bc5eb78fc794404f2288fe494720f9a119084b75569bd9eb09d2b46678bfaf39c191fb2c808ef3c833dc8982752 - languageName: node - linkType: hard - -"fast-xml-parser@npm:4.2.4": - version: 4.2.4 - resolution: "fast-xml-parser@npm:4.2.4" +"fast-xml-parser@npm:4.4.1": + version: 4.4.1 + resolution: "fast-xml-parser@npm:4.4.1" dependencies: strnum: "npm:^1.0.5" bin: fxparser: src/cli/cli.js - checksum: 10/157f64a142d37f2c937d5308d62668119e40218dab41a07d1a9563c3f92663c81fd08db0efc9fe484e0bc4dfea59827f319adc510426ff9b97c83a779d511b6f + checksum: 10/0c05ab8703630d8c857fafadbd78d0020d3a8e54310c3842179cd4a0d9d97e96d209ce885e91241f4aa9dd8dfc2fd924a682741a423d65153cad34da2032ec44 languageName: node linkType: hard "fastq@npm:^1.6.0": - version: 1.8.0 - resolution: "fastq@npm:1.8.0" + version: 1.19.1 + resolution: "fastq@npm:1.19.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10/7b7908a90e908c7c19ea5237a4cf1380665df718f5b8f643ead5245b27be105e76c04405bef28c439018976eef1e8741fde3db382d6b06435c9990fe3ce3533e + checksum: 10/75679dc226316341c4f2a6b618571f51eac96779906faecd8921b984e844d6ae42fabb2df69b1071327d398d5716693ea9c9c8941f64ac9e89ec2032ce59d730 + languageName: node + linkType: hard + +"fdir@npm:^6.4.4": + version: 6.4.4 + resolution: "fdir@npm:6.4.4" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10/d0000d6b790059b35f4ed19acc8847a66452e0bc68b28766c929ffd523e5ec2083811fc8a545e4a1d4945ce70e887b3a610c145c681073b506143ae3076342ed languageName: node linkType: hard @@ -3985,27 +4409,27 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: "npm:^5.0.1" - checksum: 10/e260f7592fd196b4421504d3597cc76f4a1ca7a9488260d533b611fc3cefd61e9a9be1417cb82d3b01ad9f9c0ff2dbf258e1026d2445e26b0cf5148ff4250429 + checksum: 10/a7095cb39e5bc32fada2aa7c7249d3f6b01bd1ce461a61b0adabacccabd9198500c6fb1f68a7c851a657e273fce2233ba869638897f3d7ed2e87a2d89b4436ea languageName: node linkType: hard -"finalhandler@npm:1.2.0": - version: 1.2.0 - resolution: "finalhandler@npm:1.2.0" +"finalhandler@npm:1.3.1": + version: 1.3.1 + resolution: "finalhandler@npm:1.3.1" dependencies: debug: "npm:2.6.9" - encodeurl: "npm:~1.0.2" + encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" on-finished: "npm:2.4.1" parseurl: "npm:~1.3.3" statuses: "npm:2.0.1" unpipe: "npm:~1.0.0" - checksum: 10/635718cb203c6d18e6b48dfbb6c54ccb08ea470e4f474ddcef38c47edcf3227feec316f886dd701235997d8af35240cae49856721ce18f539ad038665ebbf163 + checksum: 10/4babe72969b7373b5842bc9f75c3a641a4d0f8eb53af6b89fa714d4460ce03fb92b28de751d12ba415e96e7e02870c436d67412120555e2b382640535697305b languageName: node linkType: hard @@ -4020,19 +4444,29 @@ __metadata: linkType: hard "flat-cache@npm:^3.0.4": - version: 3.0.4 - resolution: "flat-cache@npm:3.0.4" + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" dependencies: - flatted: "npm:^3.1.0" + flatted: "npm:^3.2.9" + keyv: "npm:^4.5.3" rimraf: "npm:^3.0.2" - checksum: 10/9fe5d0cb97c988e3b25242e71346965fae22757674db3fca14206850af2efa3ca3b04a3ba0eba8d5e20fd8a3be80a2e14b1c2917e70ffe1acb98a8c3327e4c9f + checksum: 10/02381c6ece5e9fa5b826c9bbea481d7fd77645d96e4b0b1395238124d581d10e56f17f723d897b6d133970f7a57f0fab9148cbbb67237a0a0ffe794ba60c0c70 languageName: node linkType: hard -"flatted@npm:^3.1.0": - version: 3.2.7 - resolution: "flatted@npm:3.2.7" - checksum: 10/427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 +"flatted@npm:^3.2.9": + version: 3.3.3 + resolution: "flatted@npm:3.3.3" + checksum: 10/8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe + languageName: node + linkType: hard + +"for-each@npm:^0.3.3, for-each@npm:^0.3.5": + version: 0.3.5 + resolution: "for-each@npm:0.3.5" + dependencies: + is-callable: "npm:^1.2.7" + checksum: 10/330cc2439f85c94f4609de3ee1d32c5693ae15cdd7fe3d112c4fd9efd4ce7143f2c64ef6c2c9e0cfdb0058437f33ef05b5bdae5b98fcc903fb2143fbaf0fea0f languageName: node linkType: hard @@ -4043,6 +4477,16 @@ __metadata: languageName: node linkType: hard +"foreground-child@npm:^3.1.0": + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" + dependencies: + cross-spawn: "npm:^7.0.6" + signal-exit: "npm:^4.0.1" + checksum: 10/427b33f997a98073c0424e5c07169264a62cda806d8d2ded159b5b903fdfc8f0a1457e06b5fc35506497acb3f1e353f025edee796300209ac6231e80edece835 + languageName: node + linkType: hard + "forwarded@npm:0.2.0": version: 0.2.0 resolution: "forwarded@npm:0.2.0" @@ -4066,12 +4510,12 @@ __metadata: languageName: node linkType: hard -"fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" dependencies: - minipass: "npm:^3.0.0" - checksum: 10/03191781e94bc9a54bd376d3146f90fe8e082627c502185dbf7b9b3032f66b0b142c1115f3b2cc5936575fc1b44845ce903dd4c21bec2a8d69f3bd56f9cee9ec + minipass: "npm:^7.0.3" + checksum: 10/af143246cf6884fe26fa281621d45cfe111d34b30535a475bfa38dafe343dadb466c047a924ffc7d6b7b18265df4110224ce3803806dbb07173bf2087b648d7f languageName: node linkType: hard @@ -4093,17 +4537,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:~2.3.2": - version: 2.3.2 - resolution: "fsevents@npm:2.3.2" - dependencies: - node-gyp: "npm:latest" - checksum: 10/6b5b6f5692372446ff81cf9501c76e3e0459a4852b3b5f1fc72c103198c125a6b8c72f5f166bdd76ffb2fca261e7f6ee5565daf80dca6e571e55bcc589cc1256 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@npm:~2.3.3": +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -4123,44 +4557,40 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": - version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: node-gyp: "npm:latest" conditions: os=darwin languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10/185e20d20f10c8d661d59aac0f3b63b31132d492e1b11fcc2a93cb2c47257ebaee7407c38513efd2b35cafdf972d9beb2ea4593c1e0f3bf8f2744836928d7454 languageName: node linkType: hard -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: 10/d83f2968030678f0b8c3f2183d63dcd969344eb8b55b4eb826a94ccac6de8b87c95bebffda37a6386c74f152284eb02956ff2c496897f35d32bdc2628ac68ac5 +"function.prototype.name@npm:^1.1.6, function.prototype.name@npm:^1.1.8": + version: 1.1.8 + resolution: "function.prototype.name@npm:1.1.8" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + functions-have-names: "npm:^1.2.3" + hasown: "npm:^2.0.2" + is-callable: "npm:^1.2.7" + checksum: 10/25b9e5bea936732a6f0c0c08db58cc0d609ac1ed458c6a07ead46b32e7b9bf3fe5887796c3f83d35994efbc4fdde81c08ac64135b2c399b8f2113968d44082bc languageName: node linkType: hard -"gauge@npm:^4.0.3": - version: 4.0.4 - resolution: "gauge@npm:4.0.4" - dependencies: - aproba: "npm:^1.0.3 || ^2.0.0" - color-support: "npm:^1.1.3" - console-control-strings: "npm:^1.1.0" - has-unicode: "npm:^2.0.1" - signal-exit: "npm:^3.0.7" - string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - wide-align: "npm:^1.1.5" - checksum: 10/09535dd53b5ced6a34482b1fa9f3929efdeac02f9858569cde73cef3ed95050e0f3d095706c1689614059898924b7a74aa14042f51381a1ccc4ee5c29d2389c4 +"functions-have-names@npm:^1.2.3": + version: 1.2.3 + resolution: "functions-have-names@npm:1.2.3" + checksum: 10/0ddfd3ed1066a55984aaecebf5419fbd9344a5c38dd120ffb0739fac4496758dcf371297440528b115e4367fc46e3abc86a2cc0ff44612181b175ae967a11a05 languageName: node linkType: hard @@ -4171,15 +4601,31 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.0.2": - version: 1.2.1 - resolution: "get-intrinsic@npm:1.2.1" +"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": + version: 1.3.0 + resolution: "get-intrinsic@npm:1.3.0" dependencies: - function-bind: "npm:^1.1.1" - has: "npm:^1.0.3" - has-proto: "npm:^1.0.1" - has-symbols: "npm:^1.0.3" - checksum: 10/aee631852063f8ad0d4a374970694b5c17c2fb5c92bd1929476d7eb8798ce7aebafbf9a34022c05fd1adaa2ce846d5877a627ce1986f81fc65adf3b81824bd54 + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10/6e9dd920ff054147b6f44cb98104330e87caafae051b6d37b13384a45ba15e71af33c3baeac7cb630a0aaa23142718dcf25b45cfdd86c184c5dcb4e56d953a10 + languageName: node + linkType: hard + +"get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: "npm:^1.0.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/4fc96afdb58ced9a67558698b91433e6b037aaa6f1493af77498d7c85b141382cf223c0e5946f334fb328ee85dfe6edd06d218eaf09556f4bc4ec6005d7f5f7b languageName: node linkType: hard @@ -4197,6 +4643,17 @@ __metadata: languageName: node linkType: hard +"get-symbol-description@npm:^1.1.0": + version: 1.1.0 + resolution: "get-symbol-description@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.6" + checksum: 10/a353e3a9595a74720b40fb5bae3ba4a4f826e186e83814d93375182384265676f59e49998b9cdfac4a2225ce95a3d32a68f502a2c5619303987f1c183ab80494 + languageName: node + linkType: hard + "get-value@npm:^2.0.3, get-value@npm:^2.0.6": version: 2.0.6 resolution: "get-value@npm:2.0.6" @@ -4239,21 +4696,23 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3": - version: 7.1.6 - resolution: "glob@npm:7.1.6" +"glob@npm:^10.2.2": + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.0.4" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10/7d6ec98bc746980d5fe4d764b9c7ada727e3fbd2a7d85cd96dd95fb18638c9c54a70c692fd2ab5d68a186dc8cd9d6a4192d3df220beed891f687db179c430237 + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" + bin: + glob: dist/esm/bin.mjs + checksum: 10/698dfe11828b7efd0514cd11e573eaed26b2dff611f0400907281ce3eab0c1e56143ef9b35adc7c77ecc71fba74717b510c7c223d34ca8a98ec81777b293d4ac languageName: node linkType: hard -"glob@npm:^7.1.4": +"glob@npm:^7.1.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -4267,19 +4726,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^8.0.1": - version: 8.1.0 - resolution: "glob@npm:8.1.0" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^5.0.1" - once: "npm:^1.3.0" - checksum: 10/9aab1c75eb087c35dbc41d1f742e51d0507aa2b14c910d96fb8287107a10a22f4bbdce26fc0a3da4c69a20f7b26d62f1640b346a4f6e6becfff47f335bb1dc5e - languageName: node - linkType: hard - "global-dirs@npm:^0.1.0": version: 0.1.1 resolution: "global-dirs@npm:0.1.1" @@ -4297,11 +4743,21 @@ __metadata: linkType: hard "globals@npm:^13.19.0": - version: 13.20.0 - resolution: "globals@npm:13.20.0" + version: 13.24.0 + resolution: "globals@npm:13.24.0" dependencies: type-fest: "npm:^0.20.2" - checksum: 10/9df85cde2f0dce6ac9b3a5e08bec109d2f3b38ddd055a83867e0672c55704866d53ce6a4265859fa630624baadd46f50ca38602a13607ad86be853a8c179d3e7 + checksum: 10/62c5b1997d06674fc7191d3e01e324d3eda4d65ac9cc4e78329fa3b5c4fd42a0e1c8722822497a6964eee075255ce21ccf1eec2d83f92ef3f06653af4d0ee28e + languageName: node + linkType: hard + +"globalthis@npm:^1.0.4": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" + dependencies: + define-properties: "npm:^1.2.1" + gopd: "npm:^1.0.1" + checksum: 10/1f1fd078fb2f7296306ef9dd51019491044ccf17a59ed49d375b576ca108ff37e47f3d29aead7add40763574a992f16a5367dd1e2173b8634ef18556ab719ac4 languageName: node linkType: hard @@ -4319,6 +4775,13 @@ __metadata: languageName: node linkType: hard +"gopd@npm:^1.0.1, gopd@npm:^1.2.0": + version: 1.2.0 + resolution: "gopd@npm:1.2.0" + checksum: 10/94e296d69f92dc1c0768fcfeecfb3855582ab59a7c75e969d5f96ce50c3d201fd86d5a2857c22565764d5bb8a816c7b1e58f133ec318cd56274da36c5e3fb1a1 + languageName: node + linkType: hard + "got@npm:^6.7.1": version: 6.7.1 resolution: "got@npm:6.7.1" @@ -4338,27 +4801,13 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 languageName: node linkType: hard -"graceful-fs@npm:^4.1.2": - version: 4.2.10 - resolution: "graceful-fs@npm:4.2.10" - checksum: 10/0c83c52b62c68a944dcfb9d66b0f9f10f7d6e3d081e8067b9bfdc9e5f3a8896584d576036f82915773189eec1eba599397fc620e75c03c0610fb3d67c6713c1a - languageName: node - linkType: hard - -"grapheme-splitter@npm:^1.0.4": - version: 1.0.4 - resolution: "grapheme-splitter@npm:1.0.4" - checksum: 10/fdb2f51fd430ce881e18e44c4934ad30e59736e46213f7ad35ea5970a9ebdf7d0fe56150d15cc98230d55d2fd48c73dc6781494c38d8cf2405718366c36adb88 - languageName: node - linkType: hard - "graphemer@npm:^1.4.0": version: 1.4.0 resolution: "graphemer@npm:1.4.0" @@ -4366,6 +4815,13 @@ __metadata: languageName: node linkType: hard +"has-bigints@npm:^1.0.2": + version: 1.1.0 + resolution: "has-bigints@npm:1.1.0" + checksum: 10/90fb1b24d40d2472bcd1c8bd9dd479037ec240215869bdbff97b2be83acef57d28f7e96bdd003a21bed218d058b49097f4acc8821c05b1629cc5d48dd7bfcccd + languageName: node + linkType: hard + "has-flag@npm:^3.0.0": version: 3.0.0 resolution: "has-flag@npm:3.0.0" @@ -4380,31 +4836,37 @@ __metadata: languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: 10/eab2ab0ed1eae6d058b9bbc4c1d99d2751b29717be80d02fd03ead8b62675488de0c7359bc1fdd4b87ef6fd11e796a9631ad4d7452d9324fdada70158c2e5be7 +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" + dependencies: + es-define-property: "npm:^1.0.0" + checksum: 10/2d8c9ab8cebb572e3362f7d06139a4592105983d4317e68f7adba320fe6ddfc8874581e0971e899e633fd5f72e262830edce36d5a0bc863dad17ad20572484b2 languageName: node linkType: hard -"has-symbols@npm:^1.0.0, has-symbols@npm:^1.0.1": - version: 1.0.1 - resolution: "has-symbols@npm:1.0.1" - checksum: 10/d7a6d0b8f2b4595d6d5aafd4e020f65785779a654b52b77457f69c33e2c36400780ece296b964ae885714e4c83b503b01e2024d682d95794628d9c5a83c113bf +"has-proto@npm:^1.2.0": + version: 1.2.0 + resolution: "has-proto@npm:1.2.0" + dependencies: + dunder-proto: "npm:^1.0.0" + checksum: 10/7eaed07728eaa28b77fadccabce53f30de467ff186a766872669a833ac2e87d8922b76a22cc58339d7e0277aefe98d6d00762113b27a97cdf65adcf958970935 languageName: node linkType: hard -"has-symbols@npm:^1.0.3": - version: 1.0.3 - resolution: "has-symbols@npm:1.0.3" - checksum: 10/464f97a8202a7690dadd026e6d73b1ceeddd60fe6acfd06151106f050303eaa75855aaa94969df8015c11ff7c505f196114d22f7386b4a471038da5874cf5e9b +"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": + version: 1.1.0 + resolution: "has-symbols@npm:1.1.0" + checksum: 10/959385c98696ebbca51e7534e0dc723ada325efa3475350951363cce216d27373e0259b63edb599f72eb94d6cde8577b4b2375f080b303947e560f85692834fa languageName: node linkType: hard -"has-unicode@npm:^2.0.1": - version: 2.0.1 - resolution: "has-unicode@npm:2.0.1" - checksum: 10/041b4293ad6bf391e21c5d85ed03f412506d6623786b801c4ab39e4e6ca54993f13201bceb544d92963f9e0024e6e7fbf0cb1d84c9d6b31cb9c79c8c990d13d8 +"has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: "npm:^1.0.3" + checksum: 10/c74c5f5ceee3c8a5b8bc37719840dc3749f5b0306d818974141dda2471a1a2ca6c8e46b9d6ac222c5345df7a901c9b6f350b1e6d62763fec877e26609a401bfe languageName: node linkType: hard @@ -4447,26 +4909,26 @@ __metadata: languageName: node linkType: hard -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" +"hasown@npm:^2.0.0, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" dependencies: - function-bind: "npm:^1.1.1" - checksum: 10/a449f3185b1d165026e8d25f6a8c3390bd25c201ff4b8c1aaf948fc6a5fcfd6507310b8c00c13a3325795ea9791fcc3d79d61eafa313b5750438fc19183df57b + function-bind: "npm:^1.1.2" + checksum: 10/7898a9c1788b2862cf0f9c345a6bec77ba4a0c0983c7f19d610c382343d4f98fa260686b225dfb1f88393a66679d2ec58ee310c1d6868c081eda7918f32cc70a languageName: node linkType: hard "hosted-git-info@npm:^2.1.4": - version: 2.8.8 - resolution: "hosted-git-info@npm:2.8.8" - checksum: 10/176b7c4770852a21c0b2492d2bd34b993f3a73d092ad2137999b17a0fc65645a5f72538c0198cbaa90171413cd9a10356d9f4ab3550b38a4bd7ed78a4f68e9c1 + version: 2.8.9 + resolution: "hosted-git-info@npm:2.8.9" + checksum: 10/96da7d412303704af41c3819207a09ea2cab2de97951db4cf336bb8bce8d8e36b9a6821036ad2e55e67d3be0af8f967a7b57981203fbfb88bc05cd803407b8c3 languageName: node linkType: hard -"http-cache-semantics@npm:^4.1.0": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10/362d5ed66b12ceb9c0a328fb31200b590ab1b02f4a254a697dc796850cc4385603e75f53ec59f768b2dad3bfa1464bd229f7de278d2899a0e3beffc634b6683f +"http-cache-semantics@npm:^4.1.1": + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 languageName: node linkType: hard @@ -4483,24 +4945,23 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^5.0.0": - version: 5.0.0 - resolution: "http-proxy-agent@npm:5.0.0" +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" dependencies: - "@tootallnate/once": "npm:2" - agent-base: "npm:6" - debug: "npm:4" - checksum: 10/5ee19423bc3e0fd5f23ce991b0755699ad2a46a440ce9cec99e8126bb98448ad3479d2c0ea54be5519db5b19a4ffaa69616bac01540db18506dd4dac3dc418f0 + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10/d062acfa0cb82beeb558f1043c6ba770ea892b5fb7b28654dbc70ea2aeea55226dd34c02a294f6c1ca179a5aa483c4ea641846821b182edbd9cc5d89b54c6848 languageName: node linkType: hard -"https-proxy-agent@npm:^5.0.0": - version: 5.0.1 - resolution: "https-proxy-agent@npm:5.0.1" +"https-proxy-agent@npm:^7.0.1": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" dependencies: - agent-base: "npm:6" + agent-base: "npm:^7.1.2" debug: "npm:4" - checksum: 10/f0dce7bdcac5e8eaa0be3c7368bb8836ed010fb5b6349ffb412b172a203efe8f807d9a6681319105ea1b6901e1972c7b5ea899672a7b9aad58309f766dcbe0df + checksum: 10/784b628cbd55b25542a9d85033bdfd03d4eda630fb8b3c9477959367f3be95dc476ed2ecbb9836c359c7c698027fc7b45723a302324433590f45d6c1706e8c13 languageName: node linkType: hard @@ -4511,15 +4972,6 @@ __metadata: languageName: node linkType: hard -"humanize-ms@npm:^1.2.1": - version: 1.2.1 - resolution: "humanize-ms@npm:1.2.1" - dependencies: - ms: "npm:^2.0.0" - checksum: 10/9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 - languageName: node - linkType: hard - "iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -4553,19 +5005,19 @@ __metadata: linkType: hard "ignore@npm:^5.2.0": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 10/4f7caf5d2005da21a382d4bd1d2aa741a3bed51de185c8562dd7f899a81a620ac4fd0619b06f7029a38ae79e4e4c134399db3bd0192c703c3ef54bb82df3086c + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 10/cceb6a457000f8f6a50e1196429750d782afce5680dd878aa4221bd79972d68b3a55b4b1458fc682be978f4d3c6a249046aa0880637367216444ab7b014cfc98 languageName: node linkType: hard -"import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1": - version: 3.2.1 - resolution: "import-fresh@npm:3.2.1" +"import-fresh@npm:^3.2.1": + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" dependencies: parent-module: "npm:^1.0.0" resolve-from: "npm:^4.0.0" - checksum: 10/caef42418a087c3951fb676943a7f21ba8971aa07f9b622dff4af7edcef4160e1b172dccd85a88d7eb109cf41406a4592f70259e6b3b33aeafd042bb61f81d96 + checksum: 10/a06b19461b4879cc654d46f8a6244eb55eb053437afd4cbb6613cad6be203811849ed3e4ea038783092879487299fda24af932b86bdfff67c9055ba3612b8c87 languageName: node linkType: hard @@ -4583,20 +5035,6 @@ __metadata: languageName: node linkType: hard -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 10/cd3f5cbc9ca2d624c6a1f53f12e6b341659aba0e2d3254ae2b4464aaea8b4294cdb09616abbc59458f980531f2429784ed6a420d48d245bcad0811980c9efae9 - languageName: node - linkType: hard - -"infer-owner@npm:^1.0.4": - version: 1.0.4 - resolution: "infer-owner@npm:1.0.4" - checksum: 10/181e732764e4a0611576466b4b87dac338972b839920b2a8cde43642e4ed6bd54dc1fb0b40874728f2a2df9a1b097b8ff83b56d5f8f8e3927f837fdcb47d8a89 - languageName: node - linkType: hard - "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -4614,24 +5052,31 @@ __metadata: languageName: node linkType: hard -"ini@npm:^1.3.4": +"ini@npm:^1.3.4, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: 10/314ae176e8d4deb3def56106da8002b462221c174ddb7ce0c49ee72c8cd1f9044f7b10cc555a7d8850982c3b9ca96fc212122749f5234bc2b6fb05fb942ed566 languageName: node linkType: hard -"ini@npm:~1.3.0": - version: 1.3.5 - resolution: "ini@npm:1.3.5" - checksum: 10/3d69b7730b021fafc1ba356f1fdb7b12d97fe20ac3fbc88d5e63b59c7147236288a51ce3b6c42d5449fc99f89d94548a0005605da74d82f0c045e2bbdbc2ca79 +"internal-slot@npm:^1.1.0": + version: 1.1.0 + resolution: "internal-slot@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + hasown: "npm:^2.0.2" + side-channel: "npm:^1.1.0" + checksum: 10/1d5219273a3dab61b165eddf358815eefc463207db33c20fcfca54717da02e3f492003757721f972fd0bf21e4b426cab389c5427b99ceea4b8b670dc88ee6d4a languageName: node linkType: hard -"ip@npm:^2.0.0": - version: 2.0.0 - resolution: "ip@npm:2.0.0" - checksum: 10/1270b11e534a466fb4cf4426cbcc3a907c429389f7f4e4e3b288b42823562e88d6a509ceda8141a507de147ca506141f745005c0aa144569d94cf24a54eb52bc +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10/1ed81e06721af012306329b31f532b5e24e00cb537be18ddc905a84f19fe8f83a09a1699862bf3a1ec4b9dea93c55a3fa5faf8b5ea380431469df540f38b092c languageName: node linkType: hard @@ -4642,21 +5087,23 @@ __metadata: languageName: node linkType: hard -"is-accessor-descriptor@npm:^0.1.6": - version: 0.1.6 - resolution: "is-accessor-descriptor@npm:0.1.6" +"is-accessor-descriptor@npm:^1.0.1": + version: 1.0.1 + resolution: "is-accessor-descriptor@npm:1.0.1" dependencies: - kind-of: "npm:^3.0.2" - checksum: 10/3d629a086a9585bc16a83a8e8a3416f400023301855cafb7ccc9a1d63145b7480f0ad28877dcc2cce09492c4ec1c39ef4c071996f24ee6ac626be4217b8ffc8a + hasown: "npm:^2.0.0" + checksum: 10/df0d1da1a320e57c594e6f9b52dab8a6bece6dc90e51689d05ac8e5247164aa3eb3e9c66b37027bebfc0ea5fcce6d9503dbc41dccd82f4b57add79a307735365 languageName: node linkType: hard -"is-accessor-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-accessor-descriptor@npm:1.0.0" +"is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": + version: 3.0.5 + resolution: "is-array-buffer@npm:3.0.5" dependencies: - kind-of: "npm:^6.0.0" - checksum: 10/8e475968e9b22f9849343c25854fa24492dbe8ba0dea1a818978f9f1b887339190b022c9300d08c47fe36f1b913d70ce8cbaca00369c55a56705fdb7caed37fe + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.6" + checksum: 10/ef1095c55b963cd0dcf6f88a113e44a0aeca91e30d767c475e7d746d28d1195b10c5076b94491a7a0cd85020ca6a4923070021d74651d093dc909e9932cf689b languageName: node linkType: hard @@ -4667,6 +5114,28 @@ __metadata: languageName: node linkType: hard +"is-async-function@npm:^2.0.0": + version: 2.1.1 + resolution: "is-async-function@npm:2.1.1" + dependencies: + async-function: "npm:^1.0.0" + call-bound: "npm:^1.0.3" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10/7c2ac7efdf671e03265e74a043bcb1c0a32e226bc2a42dfc5ec8644667df668bbe14b91c08e6c1414f392f8cf86cd1d489b3af97756e2c7a49dd1ba63fd40ca6 + languageName: node + linkType: hard + +"is-bigint@npm:^1.1.0": + version: 1.1.0 + resolution: "is-bigint@npm:1.1.0" + dependencies: + has-bigints: "npm:^1.0.2" + checksum: 10/10cf327310d712fe227cfaa32d8b11814c214392b6ac18c827f157e1e85363cf9c8e2a22df526689bd5d25e53b58cc110894787afb54e138e7c504174dba15fd + languageName: node + linkType: hard + "is-binary-path@npm:^1.0.0": version: 1.0.1 resolution: "is-binary-path@npm:1.0.1" @@ -4676,6 +5145,16 @@ __metadata: languageName: node linkType: hard +"is-boolean-object@npm:^1.2.1": + version: 1.2.2 + resolution: "is-boolean-object@npm:1.2.2" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10/051fa95fdb99d7fbf653165a7e6b2cba5d2eb62f7ffa81e793a790f3fb5366c91c1b7b6af6820aa2937dd86c73aa3ca9d9ca98f500988457b1c59692c52ba911 + languageName: node + linkType: hard + "is-buffer@npm:^1.1.5": version: 1.1.6 resolution: "is-buffer@npm:1.1.6" @@ -4683,10 +5162,10 @@ __metadata: languageName: node linkType: hard -"is-callable@npm:^1.1.4, is-callable@npm:^1.2.0": - version: 1.2.0 - resolution: "is-callable@npm:1.2.0" - checksum: 10/00f052d484dc44eb00396aa53e09ecec1ea2fe21b244f10aa0d875adfeafa9f0ff2fb2d9b027bef8332b5fee93207dd0dd27e37c3b0a1327477c8c95c1cec970 +"is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 10/48a9297fb92c99e9df48706241a189da362bff3003354aea4048bd5f7b2eb0d823cd16d0a383cece3d76166ba16d85d9659165ac6fcce1ac12e6c649d66dbdb9 languageName: node linkType: hard @@ -4701,50 +5180,62 @@ __metadata: languageName: node linkType: hard -"is-data-descriptor@npm:^0.1.4": - version: 0.1.4 - resolution: "is-data-descriptor@npm:0.1.4" +"is-core-module@npm:^2.16.0": + version: 2.16.1 + resolution: "is-core-module@npm:2.16.1" dependencies: - kind-of: "npm:^3.0.2" - checksum: 10/5c622e078ba933a78338ae398a3d1fc5c23332b395312daf4f74bab4afb10d061cea74821add726cb4db8b946ba36217ee71a24fe71dd5bca4632edb7f6aad87 + hasown: "npm:^2.0.2" + checksum: 10/452b2c2fb7f889cbbf7e54609ef92cf6c24637c568acc7e63d166812a0fb365ae8a504c333a29add8bdb1686704068caa7f4e4b639b650dde4f00a038b8941fb languageName: node linkType: hard -"is-data-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-data-descriptor@npm:1.0.0" +"is-data-descriptor@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-descriptor@npm:1.0.1" dependencies: - kind-of: "npm:^6.0.0" - checksum: 10/b8b1f13a535800a9f35caba2743b2cfd1e76312c0f94248c333d3b724d6ac6e07f06011e8b00eb2442f27dfc8fb71faf3dd52ced6bee41bb836be3df5d7811ee + hasown: "npm:^2.0.0" + checksum: 10/49b36e903b31623b0c5b416e182e366810ef97a3a19ab0e6cd501eb5599112680b7d9e768b07a84fb52aa2510a92b3eb51a3e18ce8d5f7978a49f4b50e6ec6dd languageName: node linkType: hard -"is-date-object@npm:^1.0.1": +"is-data-view@npm:^1.0.1, is-data-view@npm:^1.0.2": version: 1.0.2 - resolution: "is-date-object@npm:1.0.2" - checksum: 10/96c56c04631f866b3a3aea4b889eac6120c13d8a06dc7e105479ffd6f57e5ea3668f1d779ef30063d4b27aa8e9b235ea7d15bbdab54b056affc678c4769ff143 + resolution: "is-data-view@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + get-intrinsic: "npm:^1.2.6" + is-typed-array: "npm:^1.1.13" + checksum: 10/357e9a48fa38f369fd6c4c3b632a3ab2b8adca14997db2e4b3fe94c4cd0a709af48e0fb61b02c64a90c0dd542fd489d49c2d03157b05ae6c07f5e4dec9e730a8 + languageName: node + linkType: hard + +"is-date-object@npm:^1.0.5, is-date-object@npm:^1.1.0": + version: 1.1.0 + resolution: "is-date-object@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10/3a811b2c3176fb31abee1d23d3dc78b6c65fd9c07d591fcb67553cab9e7f272728c3dd077d2d738b53f9a2103255b0a6e8dfc9568a7805c56a78b2563e8d1dec languageName: node linkType: hard "is-descriptor@npm:^0.1.0": - version: 0.1.6 - resolution: "is-descriptor@npm:0.1.6" + version: 0.1.7 + resolution: "is-descriptor@npm:0.1.7" dependencies: - is-accessor-descriptor: "npm:^0.1.6" - is-data-descriptor: "npm:^0.1.4" - kind-of: "npm:^5.0.0" - checksum: 10/b946ba842187c2784a5a0d67bd0e0271b14678f4fdce7d2295dfda9201f3408f55f56e11e5e66bfa4d2b9d45655b6105ad872ad7d37fb63f582587464fd414d7 + is-accessor-descriptor: "npm:^1.0.1" + is-data-descriptor: "npm:^1.0.1" + checksum: 10/38783182c3d83f839a9fa3e87b4d6de11fa9639833ed98993ea51aea2296b2da155121956e148695a738228871d1057c5f963d0b1c857bb8a4a38d8dd9ceeb56 languageName: node linkType: hard "is-descriptor@npm:^1.0.0, is-descriptor@npm:^1.0.2": - version: 1.0.2 - resolution: "is-descriptor@npm:1.0.2" + version: 1.0.3 + resolution: "is-descriptor@npm:1.0.3" dependencies: - is-accessor-descriptor: "npm:^1.0.0" - is-data-descriptor: "npm:^1.0.0" - kind-of: "npm:^6.0.2" - checksum: 10/e68059b333db331d5ea68cb367ce12fc6810853ced0e2221e6747143bbdf223dee73ebe8f331bafe04e34fdbe3da584b6af3335e82eabfaa33d5026efa33ca34 + is-accessor-descriptor: "npm:^1.0.1" + is-data-descriptor: "npm:^1.0.1" + checksum: 10/b940d04d93adaffb749b3ca7f7f6d73dd3c5582b674f372513ecb5511a8a3f3ff4a24f4c1161cb10e48fe4886f9e84c09fa71785def27905ca8df1197e563dc6 languageName: node linkType: hard @@ -4780,6 +5271,15 @@ __metadata: languageName: node linkType: hard +"is-finalizationregistry@npm:^1.1.0": + version: 1.1.1 + resolution: "is-finalizationregistry@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10/0bfb145e9a1ba852ddde423b0926d2169ae5fe9e37882cde9e8f69031281a986308df4d982283e152396e88b86562ed2256cbaa5e6390fb840a4c25ab54b8a80 + languageName: node + linkType: hard + "is-fullwidth-code-point@npm:^2.0.0": version: 2.0.0 resolution: "is-fullwidth-code-point@npm:2.0.0" @@ -4794,6 +5294,18 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.10": + version: 1.1.0 + resolution: "is-generator-function@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + get-proto: "npm:^1.0.0" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10/5906ff51a856a5fbc6b90a90fce32040b0a6870da905f98818f1350f9acadfc9884f7c3dec833fce04b83dd883937b86a190b6593ede82e8b1af8b6c4ecf7cbd + languageName: node + linkType: hard + "is-glob@npm:^3.1.0": version: 3.1.0 resolution: "is-glob@npm:3.1.0" @@ -4803,16 +5315,7 @@ __metadata: languageName: node linkType: hard -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1": - version: 4.0.1 - resolution: "is-glob@npm:4.0.1" - dependencies: - is-extglob: "npm:^2.1.1" - checksum: 10/998cdc412db39a9ad10b5484bbbe43f8dfb6eb0467380c49d53a5105108ac2e590cca3c3ac0ff5e0dcc9c3342c5c235e77fd699576bcd16384eb5a62d4dd086a - languageName: node - linkType: hard - -"is-glob@npm:^4.0.3": +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -4831,10 +5334,10 @@ __metadata: languageName: node linkType: hard -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 10/93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 +"is-map@npm:^2.0.3": + version: 2.0.3 + resolution: "is-map@npm:2.0.3" + checksum: 10/8de7b41715b08bcb0e5edb0fb9384b80d2d5bcd10e142188f33247d19ff078abaf8e9b6f858e2302d8d05376a26a55cd23a3c9f8ab93292b02fcd2cc9e4e92bb languageName: node linkType: hard @@ -4845,6 +5348,16 @@ __metadata: languageName: node linkType: hard +"is-number-object@npm:^1.1.1": + version: 1.1.1 + resolution: "is-number-object@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10/a5922fb8779ab1ea3b8a9c144522b3d0bea5d9f8f23f7a72470e61e1e4df47714e28e0154ac011998b709cce260c3c9447ad3cd24a96c2f2a0abfdb2cbdc76c8 + languageName: node + linkType: hard + "is-number@npm:^3.0.0": version: 3.0.0 resolution: "is-number@npm:3.0.0" @@ -4907,12 +5420,15 @@ __metadata: languageName: node linkType: hard -"is-regex@npm:^1.1.0": - version: 1.1.1 - resolution: "is-regex@npm:1.1.1" +"is-regex@npm:^1.2.1": + version: 1.2.1 + resolution: "is-regex@npm:1.2.1" dependencies: - has-symbols: "npm:^1.0.1" - checksum: 10/1ed55cadc258a4fb88fb44e74e1825cb81ad8ffba83ea03e18125ed6c3c6054d0799cabdb67445d0bdfd568a99f629656a1ab67862ea0c099fd641d49f9fb244 + call-bound: "npm:^1.0.2" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.2" + checksum: 10/c42b7efc5868a5c9a4d8e6d3e9816e8815c611b09535c00fead18a1138455c5cb5e1887f0023a467ad3f9c419d62ba4dc3d9ba8bafe55053914d6d6454a945d2 languageName: node linkType: hard @@ -4923,6 +5439,22 @@ __metadata: languageName: node linkType: hard +"is-set@npm:^2.0.3": + version: 2.0.3 + resolution: "is-set@npm:2.0.3" + checksum: 10/5685df33f0a4a6098a98c72d94d67cad81b2bc72f1fb2091f3d9283c4a1c582123cd709145b02a9745f0ce6b41e3e43f1c944496d1d74d4ea43358be61308669 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.4": + version: 1.0.4 + resolution: "is-shared-array-buffer@npm:1.0.4" + dependencies: + call-bound: "npm:^1.0.3" + checksum: 10/0380d7c60cc692856871526ffcd38a8133818a2ee42d47bb8008248a0cd2121d8c8b5f66b6da3cac24bc5784553cacb6faaf678f66bc88c6615b42af2825230e + languageName: node + linkType: hard + "is-stream@npm:^1.0.0, is-stream@npm:^1.1.0": version: 1.1.0 resolution: "is-stream@npm:1.1.0" @@ -4937,12 +5469,59 @@ __metadata: languageName: node linkType: hard -"is-symbol@npm:^1.0.2": - version: 1.0.3 - resolution: "is-symbol@npm:1.0.3" +"is-string@npm:^1.1.1": + version: 1.1.1 + resolution: "is-string@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10/5277cb9e225a7cc8a368a72623b44a99f2cfa139659c6b203553540681ad4276bfc078420767aad0e73eef5f0bd07d4abf39a35d37ec216917879d11cebc1f8b + languageName: node + linkType: hard + +"is-symbol@npm:^1.0.4, is-symbol@npm:^1.1.1": + version: 1.1.1 + resolution: "is-symbol@npm:1.1.1" + dependencies: + call-bound: "npm:^1.0.2" + has-symbols: "npm:^1.1.0" + safe-regex-test: "npm:^1.1.0" + checksum: 10/db495c0d8cd0a7a66b4f4ef7fccee3ab5bd954cb63396e8ac4d32efe0e9b12fdfceb851d6c501216a71f4f21e5ff20fc2ee845a3d52d455e021c466ac5eb2db2 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15": + version: 1.1.15 + resolution: "is-typed-array@npm:1.1.15" + dependencies: + which-typed-array: "npm:^1.1.16" + checksum: 10/e8cf60b9ea85667097a6ad68c209c9722cfe8c8edf04d6218366469e51944c5cc25bae45ffb845c23f811d262e4314d3b0168748eb16711aa34d12724cdf0735 + languageName: node + linkType: hard + +"is-weakmap@npm:^2.0.2": + version: 2.0.2 + resolution: "is-weakmap@npm:2.0.2" + checksum: 10/a7b7e23206c542dcf2fa0abc483142731788771527e90e7e24f658c0833a0d91948a4f7b30d78f7a65255a48512e41a0288b778ba7fc396137515c12e201fd11 + languageName: node + linkType: hard + +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.1": + version: 1.1.1 + resolution: "is-weakref@npm:1.1.1" dependencies: - has-symbols: "npm:^1.0.1" - checksum: 10/4854604be4abb5f9d885d4bbc9f9318b7dbda9402fbe172c09861bb8910d97e70fac6dabbf1023a7ec56986f457c92abb08f1c99decce83c06c944130a0b1cd1 + call-bound: "npm:^1.0.3" + checksum: 10/543506fd8259038b371bb083aac25b16cb4fd8b12fc58053aa3d45ac28dfd001cd5c6dffbba7aeea4213c74732d46b6cb2cfb5b412eed11f2db524f3f97d09a0 + languageName: node + linkType: hard + +"is-weakset@npm:^2.0.3": + version: 2.0.4 + resolution: "is-weakset@npm:2.0.4" + dependencies: + call-bound: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.6" + checksum: 10/1d5e1d0179beeed3661125a6faa2e59bfb48afda06fc70db807f178aa0ebebc3758fb6358d76b3d528090d5ef85148c345dcfbf90839592fe293e3e5e82f2134 languageName: node linkType: hard @@ -4969,6 +5548,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: 10/1d8bc7911e13bb9f105b1b3e0b396c787a9e63046af0b8fe0ab1414488ab06b2b099b87a2d8a9e31d21c9a6fad773c7fc8b257c4880f2d957274479d28ca3414 + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -4976,6 +5562,13 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10/7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + "isobject@npm:^2.0.0": version: 2.1.0 resolution: "isobject@npm:2.1.0" @@ -4992,6 +5585,28 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 10/96f8786eaab98e4bf5b2a5d6d9588ea46c4d06bbc4f2eb861fdd7b6b182b16f71d8a70e79820f335d52653b16d4843b29dd9cdcf38ae80406756db9199497cf3 + languageName: node + linkType: hard + +"jiti@npm:^2.4.2": + version: 2.4.2 + resolution: "jiti@npm:2.4.2" + bin: + jiti: lib/jiti-cli.mjs + checksum: 10/e2b07eb2e3fbb245e29ad288dddecab31804967fc84d5e01d39858997d2743b5e248946defcecf99272275a00284ecaf7ec88b8c841331324f0c946d8274414b + languageName: node + linkType: hard + "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -5010,12 +5625,26 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:^2.5.1": - version: 2.5.2 - resolution: "jsesc@npm:2.5.2" +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10/bebe7ae829bbd586ce8cbe83501dd8cb8c282c8902a8aeeed0a073a89dc37e8103b1244f3c6acd60278bcbfe12d93a3f83c9ac396868a3b3bbc3c5e5e3b648ef + languageName: node + linkType: hard + +"jsesc@npm:^3.0.2": + version: 3.1.0 + resolution: "jsesc@npm:3.1.0" bin: jsesc: bin/jsesc - checksum: 10/d2096abdcdec56969764b40ffc91d4a23408aa2f351b4d1c13f736f25476643238c43fdbaf38a191c26b1b78fd856d965f5d4d0dde7b89459cd94025190cdf13 + checksum: 10/20bd37a142eca5d1794f354db8f1c9aeb54d85e1f5c247b371de05d23a9751ecd7bd3a9c4fc5298ea6fa09a100dafb4190fa5c98c6610b75952c3487f3ce7967 + languageName: node + linkType: hard + +"json-buffer@npm:3.0.1": + version: 3.0.1 + resolution: "json-buffer@npm:3.0.1" + checksum: 10/82876154521b7b68ba71c4f969b91572d1beabadd87bd3a6b236f85fbc7dc4695089191ed60bb59f9340993c51b33d479f45b6ba9f3548beb519705281c32c3c languageName: node linkType: hard @@ -5056,6 +5685,15 @@ __metadata: languageName: node linkType: hard +"keyv@npm:^4.5.3": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" + dependencies: + json-buffer: "npm:3.0.1" + checksum: 10/167eb6ef64cc84b6fa0780ee50c9de456b422a1e18802209234f7c2cf7eae648c7741f32e50d7e24ccb22b24c13154070b01563d642755b156c357431a191e75 + languageName: node + linkType: hard + "kind-of@npm:^3.0.2, kind-of@npm:^3.0.3, kind-of@npm:^3.2.0": version: 3.2.2 resolution: "kind-of@npm:3.2.2" @@ -5074,14 +5712,7 @@ __metadata: languageName: node linkType: hard -"kind-of@npm:^5.0.0": - version: 5.1.0 - resolution: "kind-of@npm:5.1.0" - checksum: 10/acf7cc73881f27629f700a80de77ff7fe4abc9430eac7ddb09117f75126e578ee8d7e44c4dacb6a9e802d5d881abf007ee6af3cfbe55f8b5cf0a7fdc49a02aa3 - languageName: node - linkType: hard - -"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2": +"kind-of@npm:^6.0.2": version: 6.0.3 resolution: "kind-of@npm:6.0.3" checksum: 10/5873d303fb36aad875b7538798867da2ae5c9e328d67194b0162a3659a627d22f742fc9c4ae95cd1704132a24b00cae5041fc00c0f6ef937dc17080dc4dbb962 @@ -5107,6 +5738,116 @@ __metadata: languageName: node linkType: hard +"lightningcss-darwin-arm64@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-darwin-arm64@npm:1.30.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-x64@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-darwin-x64@npm:1.30.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-freebsd-x64@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-freebsd-x64@npm:1.30.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-linux-arm-gnueabihf@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.30.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"lightningcss-linux-arm64-gnu@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-arm64-gnu@npm:1.30.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-arm64-musl@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-arm64-musl@npm:1.30.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-linux-x64-gnu@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-x64-gnu@npm:1.30.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-x64-musl@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-x64-musl@npm:1.30.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-win32-arm64-msvc@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-win32-arm64-msvc@npm:1.30.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-win32-x64-msvc@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-win32-x64-msvc@npm:1.30.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"lightningcss@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss@npm:1.30.1" + dependencies: + detect-libc: "npm:^2.0.3" + lightningcss-darwin-arm64: "npm:1.30.1" + lightningcss-darwin-x64: "npm:1.30.1" + lightningcss-freebsd-x64: "npm:1.30.1" + lightningcss-linux-arm-gnueabihf: "npm:1.30.1" + lightningcss-linux-arm64-gnu: "npm:1.30.1" + lightningcss-linux-arm64-musl: "npm:1.30.1" + lightningcss-linux-x64-gnu: "npm:1.30.1" + lightningcss-linux-x64-musl: "npm:1.30.1" + lightningcss-win32-arm64-msvc: "npm:1.30.1" + lightningcss-win32-x64-msvc: "npm:1.30.1" + dependenciesMeta: + lightningcss-darwin-arm64: + optional: true + lightningcss-darwin-x64: + optional: true + lightningcss-freebsd-x64: + optional: true + lightningcss-linux-arm-gnueabihf: + optional: true + lightningcss-linux-arm64-gnu: + optional: true + lightningcss-linux-arm64-musl: + optional: true + lightningcss-linux-x64-gnu: + optional: true + lightningcss-linux-x64-musl: + optional: true + lightningcss-win32-arm64-msvc: + optional: true + lightningcss-win32-x64-msvc: + optional: true + checksum: 10/6c921135216cc498dfcb87e35dffe8432e99306cbd58009c598b1daf20c81cc14535abbd4c1066e5d1faf4080ed44a2995e8ecc343633db4897a2d041b76fb05 + languageName: node + linkType: hard + "load-json-file@npm:^4.0.0": version: 4.0.0 resolution: "load-json-file@npm:4.0.0" @@ -5153,6 +5894,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 10/e6e90267360476720fa8e83cc168aa2bf0311f3f2eea20a6ba78b90a885ae72071d9db132f40fda4129c803e7dcec3a6b6a6fbb44ca90b081630b810b5d6a41a + languageName: node + linkType: hard + "lru-cache@npm:^4.0.1": version: 4.1.5 resolution: "lru-cache@npm:4.1.5" @@ -5172,19 +5920,12 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" +"magic-string@npm:^0.30.17": + version: 0.30.17 + resolution: "magic-string@npm:0.30.17" dependencies: - yallist: "npm:^4.0.0" - checksum: 10/fc1fe2ee205f7c8855fa0f34c1ab0bcf14b6229e35579ec1fd1079f31d6fc8ef8eb6fd17f2f4d99788d7e339f50e047555551ebd5e434dda503696e7c6591825 - languageName: node - linkType: hard - -"lru-cache@npm:^7.7.1": - version: 7.18.3 - resolution: "lru-cache@npm:7.18.3" - checksum: 10/6029ca5aba3aacb554e919d7ef804fffd4adfc4c83db00fac8248c7c78811fb6d4b6f70f7fd9d55032b3823446546a007edaa66ad1f2377ae833bd983fac5d98 + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + checksum: 10/2f71af2b0afd78c2e9012a29b066d2c8ba45a9cd0c8070f7fd72de982fb1c403b4e3afdb1dae00691d56885ede66b772ef6bedf765e02e3a7066208fe2fec4aa languageName: node linkType: hard @@ -5197,27 +5938,22 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^10.0.3": - version: 10.2.1 - resolution: "make-fetch-happen@npm:10.2.1" +"make-fetch-happen@npm:^14.0.3": + version: 14.0.3 + resolution: "make-fetch-happen@npm:14.0.3" dependencies: - agentkeepalive: "npm:^4.2.1" - cacache: "npm:^16.1.0" - http-cache-semantics: "npm:^4.1.0" - http-proxy-agent: "npm:^5.0.0" - https-proxy-agent: "npm:^5.0.0" - is-lambda: "npm:^1.0.1" - lru-cache: "npm:^7.7.1" - minipass: "npm:^3.1.6" - minipass-collect: "npm:^1.0.2" - minipass-fetch: "npm:^2.0.3" + "@npmcli/agent": "npm:^3.0.0" + cacache: "npm:^19.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^0.6.3" + negotiator: "npm:^1.0.0" + proc-log: "npm:^5.0.0" promise-retry: "npm:^2.0.1" - socks-proxy-agent: "npm:^7.0.0" - ssri: "npm:^9.0.0" - checksum: 10/fef5acb865a46f25ad0b5ad7d979799125db5dbb24ea811ffa850fbb804bc8e495df2237a8ec3a4fc6250e73c2f95549cca6d6d36a73b1faa61224504eb1188f + ssri: "npm:^12.0.0" + checksum: 10/fce0385840b6d86b735053dfe941edc2dd6468fda80fe74da1eeff10cbd82a75760f406194f2bc2fa85b99545b2bc1f84c08ddf994b21830775ba2d1a87e8bdf languageName: node linkType: hard @@ -5237,6 +5973,13 @@ __metadata: languageName: node linkType: hard +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 10/11df2eda46d092a6035479632e1ec865b8134bdfc4bd9e571a656f4191525404f13a283a515938c3a8de934dbfd9c09674d9da9fa831e6eb7e22b50b197d2edd + languageName: node + linkType: hard + "media-typer@npm:0.3.0": version: 0.3.0 resolution: "media-typer@npm:0.3.0" @@ -5258,10 +6001,10 @@ __metadata: languageName: node linkType: hard -"merge-descriptors@npm:1.0.1": - version: 1.0.1 - resolution: "merge-descriptors@npm:1.0.1" - checksum: 10/5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 +"merge-descriptors@npm:1.0.3": + version: 1.0.3 + resolution: "merge-descriptors@npm:1.0.3" + checksum: 10/52117adbe0313d5defa771c9993fe081e2d2df9b840597e966aadafde04ae8d0e3da46bac7ca4efc37d4d2b839436582659cd49c6a43eacb3fe3050896a105d1 languageName: node linkType: hard @@ -5307,30 +6050,30 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" +"micromatch@npm:^4.0.8": + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" dependencies: - braces: "npm:^3.0.2" + braces: "npm:^3.0.3" picomatch: "npm:^2.3.1" - checksum: 10/a749888789fc15cac0e03273844dbd749f9f8e8d64e70c564bcf06a033129554c789bb9e30d7566d7ff6596611a08e58ac12cf2a05f6e3c9c47c50c4c7e12fa2 + checksum: 10/6bf2a01672e7965eb9941d1f02044fad2bd12486b5553dc1116ff24c09a8723157601dc992e74c911d896175918448762df3b3fd0a6b61037dd1a9766ddfbf58 languageName: node linkType: hard -"mime-db@npm:1.44.0": - version: 1.44.0 - resolution: "mime-db@npm:1.44.0" - checksum: 10/7cde7b1d8e9ac68033a40686a944f42f3007d0c58fb78ed5720ac999d9c724b9330ee15ba40338d93eb17653d769736955b104d9c52666b37b001791649f8d6a - languageName: node - linkType: hard - -"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": +"mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" checksum: 10/54bb60bf39e6f8689f6622784e668a3d7f8bed6b0d886f5c3c446cb3284be28b30bf707ed05d0fe44a036f8469976b2629bbea182684977b084de9da274694d7 languageName: node linkType: hard +"mime-db@npm:>= 1.43.0 < 2": + version: 1.54.0 + resolution: "mime-db@npm:1.54.0" + checksum: 10/9e7834be3d66ae7f10eaa69215732c6d389692b194f876198dca79b2b90cbf96688d9d5d05ef7987b20f749b769b11c01766564264ea5f919c88b32a29011311 + languageName: node + linkType: hard + "mime-db@npm:~1.33.0": version: 1.33.0 resolution: "mime-db@npm:1.33.0" @@ -5347,16 +6090,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:~2.1.24": - version: 2.1.27 - resolution: "mime-types@npm:2.1.27" - dependencies: - mime-db: "npm:1.44.0" - checksum: 10/056a86257296dd7a73d6c74f8adb118c2dc8beaa4c46898042e275fcc85aaf2a33a8533cb4bd38c97a42512146e3c4fa0140c3a9508456260ee444474b7fc618 - languageName: node - linkType: hard - -"mime-types@npm:~2.1.34": +"mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -5381,7 +6115,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:3.1.2, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:3.1.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -5390,52 +6124,43 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.4": - version: 3.0.4 - resolution: "minimatch@npm:3.0.4" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10/3b3f17f76582417dd139646505f1d1bb5f148ea5191eb98fe73cd41224a678dadb94cc674c7d06b36de4ab5c303f039cfd7cd2d089348d6f70d04db169cf3770 - languageName: node - linkType: hard - -"minimatch@npm:^5.0.1": - version: 5.1.6 - resolution: "minimatch@npm:5.1.6" +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 10/126b36485b821daf96d33b5c821dac600cc1ab36c87e7a532594f9b1652b1fa89a1eebcaad4dff17c764dce1a7ac1531327f190fed5f97d8f6e5f889c116c429 + checksum: 10/dd6a8927b063aca6d910b119e1f2df6d2ce7d36eab91de83167dd136bb85e1ebff97b0d3de1cb08bd1f7e018ca170b4962479fefab5b2a69e2ae12cb2edc8348 languageName: node linkType: hard "minimist@npm:^1.2.0": - version: 1.2.6 - resolution: "minimist@npm:1.2.6" - checksum: 10/b956a7d48669c5007f0afce100a92d3af18e77939a25b5b4f62e9ea07c2777033608327e14c2af85684d5cd504f623f2a04d30a4a43379d21dd3c6dcf12b8ab8 + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f languageName: node linkType: hard -"minipass-collect@npm:^1.0.2": - version: 1.0.2 - resolution: "minipass-collect@npm:1.0.2" +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" dependencies: - minipass: "npm:^3.0.0" - checksum: 10/14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 + minipass: "npm:^7.0.3" + checksum: 10/b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 languageName: node linkType: hard -"minipass-fetch@npm:^2.0.3": - version: 2.1.2 - resolution: "minipass-fetch@npm:2.1.2" +"minipass-fetch@npm:^4.0.0": + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" dependencies: encoding: "npm:^0.1.13" - minipass: "npm:^3.1.6" + minipass: "npm:^7.0.3" minipass-sized: "npm:^1.0.3" - minizlib: "npm:^2.1.2" + minizlib: "npm:^3.0.1" dependenciesMeta: encoding: optional: true - checksum: 10/8cfc589563ae2a11eebbf79121ef9a526fd078fca949ed3f1e4a51472ca4a4aad89fcea1738982ce9d7d833116ecc9c6ae9ebbd844832a94e3f4a3d4d1b9d3b9 + checksum: 10/7ddfebdbb87d9866e7b5f7eead5a9e3d9d507992af932a11d275551f60006cf7d9178e66d586dbb910894f3e3458d27c0ddf93c76e94d49d0a54a541ddc1263d languageName: node linkType: hard @@ -5466,7 +6191,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^3.0.0, minipass@npm:^3.1.1, minipass@npm:^3.1.6": +"minipass@npm:^3.0.0": version: 3.3.6 resolution: "minipass@npm:3.3.6" dependencies: @@ -5475,20 +6200,19 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 10/61682162d29f45d3152b78b08bab7fb32ca10899bc5991ffe98afc18c9e9543bd1e3be94f8b8373ba6262497db63607079dc242ea62e43e7b2270837b7347c93 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950 languageName: node linkType: hard -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" +"minizlib@npm:^3.0.1": + version: 3.0.2 + resolution: "minizlib@npm:3.0.2" dependencies: - minipass: "npm:^3.0.0" - yallist: "npm:^4.0.0" - checksum: 10/ae0f45436fb51344dcb87938446a32fbebb540d0e191d63b35e1c773d47512e17307bf54aa88326cc6d176594d00e4423563a091f7266c2f9a6872cdc1e234d1 + minipass: "npm:^7.1.2" + checksum: 10/c075bed1594f68dcc8c35122333520112daefd4d070e5d0a228bd4cf5580e9eed3981b96c0ae1d62488e204e80fd27b2b9d0068ca9a5ef3993e9565faf63ca41 languageName: node linkType: hard @@ -5502,16 +6226,16 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" bin: - mkdirp: bin/cmd.js - checksum: 10/d71b8dcd4b5af2fe13ecf3bd24070263489404fe216488c5ba7e38ece1f54daf219e72a833a3a2dc404331e870e9f44963a33399589490956bff003a3404d3b2 + mkdirp: dist/cjs/src/bin.js + checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba languageName: node linkType: hard -"mongodb-connection-string-url@npm:^2.5.4, mongodb-connection-string-url@npm:^2.6.0": +"mongodb-connection-string-url@npm:^2.6.0": version: 2.6.0 resolution: "mongodb-connection-string-url@npm:2.6.0" dependencies: @@ -5521,47 +6245,65 @@ __metadata: languageName: node linkType: hard +"mongodb-connection-string-url@npm:^3.0.0": + version: 3.0.2 + resolution: "mongodb-connection-string-url@npm:3.0.2" + dependencies: + "@types/whatwg-url": "npm:^11.0.2" + whatwg-url: "npm:^14.1.0 || ^13.0.0" + checksum: 10/99ac939a67cc963b90cfe70a8e45250a8386c531be7d22ffa5d1f3e5dd2406b149fb823b91ac161e4a4a29dfac754b49bca8f6dd786cfc66ae0ca80db5f5f23d + languageName: node + linkType: hard + "mongodb@npm:*": - version: 5.6.0 - resolution: "mongodb@npm:5.6.0" + version: 6.16.0 + resolution: "mongodb@npm:6.16.0" dependencies: - bson: "npm:^5.3.0" - mongodb-connection-string-url: "npm:^2.6.0" - saslprep: "npm:^1.0.3" - socks: "npm:^2.7.1" + "@mongodb-js/saslprep": "npm:^1.1.9" + bson: "npm:^6.10.3" + mongodb-connection-string-url: "npm:^3.0.0" peerDependencies: - "@aws-sdk/credential-providers": ^3.201.0 - mongodb-client-encryption: ">=2.3.0 <3" + "@aws-sdk/credential-providers": ^3.188.0 + "@mongodb-js/zstd": ^1.1.0 || ^2.0.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: ">=6.0.0 <7" snappy: ^7.2.2 - dependenciesMeta: - saslprep: - optional: true + socks: ^2.7.1 peerDependenciesMeta: "@aws-sdk/credential-providers": optional: true + "@mongodb-js/zstd": + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true mongodb-client-encryption: optional: true snappy: optional: true - checksum: 10/9ad910e71022b77d9012cd846c9a70226050d15d24fbcc6a251b421b35d923313b7c2d8eb5e724aa1de00c91226413fb0a3e18aa140a5e8531cee6bbe598a087 + socks: + optional: true + checksum: 10/eb47da9ef00331aca1804426424a8630f9e42c48bf6021786ebb1766b1d53bda62c64498b41627b5fe5c01260ec5ca2e8cbc2468e394df5d5b874cee646e9c06 languageName: node linkType: hard "mongodb@npm:^4.12.1": - version: 4.16.0 - resolution: "mongodb@npm:4.16.0" + version: 4.17.2 + resolution: "mongodb@npm:4.17.2" dependencies: "@aws-sdk/credential-providers": "npm:^3.186.0" + "@mongodb-js/saslprep": "npm:^1.1.0" bson: "npm:^4.7.2" - mongodb-connection-string-url: "npm:^2.5.4" - saslprep: "npm:^1.0.3" + mongodb-connection-string-url: "npm:^2.6.0" socks: "npm:^2.7.1" dependenciesMeta: "@aws-sdk/credential-providers": optional: true - saslprep: + "@mongodb-js/saslprep": optional: true - checksum: 10/86624ba95fd28e38e2407190b0d3145c3f0ce06a83545f1ceddb3cc202bbb869608783aa4c08ef827b7863c3f60dd5cdb9b497befb47c01ec16c306f5089c514 + checksum: 10/e9f252c13a12b6339b5b4912c32d40f447eaeae77f0b0d0e36b7fbaa6800eae69ae68c6e6f005f97e90c90ad2a9f56369a0924963b83f959c83a4c1398093642 languageName: node linkType: hard @@ -5572,14 +6314,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 10/673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f - languageName: node - linkType: hard - -"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1": +"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -5587,20 +6322,20 @@ __metadata: linkType: hard "nan@npm:^2.12.1": - version: 2.17.0 - resolution: "nan@npm:2.17.0" + version: 2.22.2 + resolution: "nan@npm:2.22.2" dependencies: node-gyp: "npm:latest" - checksum: 10/bba1efee2475afb0cce154300b554863fb4bb0a683a28f5d0fa7390794b3b4381356aabeab6472c70651d9c8a2830e7595963f3ec0aa2008e5c4d83dbeb820fa + checksum: 10/bee49de633650213970596ffbdf036bfe2109ff283a40f7742c3aa6d1fc15b9836f62bfee82192b879f56ab5f9fa9a1e5c58a908a50e5c87d91fb2118ef70827 languageName: node linkType: hard -"nanoid@npm:^3.3.7": - version: 3.3.7 - resolution: "nanoid@npm:3.3.7" +"nanoid@npm:^3.3.8": + version: 3.3.11 + resolution: "nanoid@npm:3.3.11" bin: nanoid: bin/nanoid.cjs - checksum: 10/ac1eb60f615b272bccb0e2b9cd933720dad30bf9708424f691b8113826bb91aca7e9d14ef5d9415a6ba15c266b37817256f58d8ce980c82b0ba3185352565679 + checksum: 10/73b5afe5975a307aaa3c95dfe3334c52cdf9ae71518176895229b8d65ab0d1c0417dd081426134eb7571c055720428ea5d57c645138161e7d10df80815527c48 languageName: node linkType: hard @@ -5637,13 +6372,20 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: 10/2723fb822a17ad55c93a588a4bc44d53b22855bf4be5499916ca0cab1e7165409d0b288ba2577d7b029f10ce18cf2ed8e703e5af31c984e1e2304277ef979837 languageName: node linkType: hard +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10/b5734e87295324fabf868e36fb97c84b7d7f3156ec5f4ee5bf6e488079c11054f818290fc33804cef7b1ee21f55eeb14caea83e7dafae6492a409b3e573153e5 + languageName: node + linkType: hard + "nice-try@npm:^1.0.4": version: 1.0.5 resolution: "nice-try@npm:1.0.5" @@ -5652,29 +6394,29 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 9.3.1 - resolution: "node-gyp@npm:9.3.1" + version: 11.2.0 + resolution: "node-gyp@npm:11.2.0" dependencies: env-paths: "npm:^2.2.0" - glob: "npm:^7.1.4" + exponential-backoff: "npm:^3.1.1" graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^10.0.3" - nopt: "npm:^6.0.0" - npmlog: "npm:^6.0.0" - rimraf: "npm:^3.0.2" + make-fetch-happen: "npm:^14.0.3" + nopt: "npm:^8.0.0" + proc-log: "npm:^5.0.0" semver: "npm:^7.3.5" - tar: "npm:^6.1.2" - which: "npm:^2.0.2" + tar: "npm:^7.4.3" + tinyglobby: "npm:^0.2.12" + which: "npm:^5.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10/e9345b22be0a3256af87a16ba9604362cd8e4db304e67e71dd83bb8e573f3fdbaf69e359b5af572a14a98730cc3e1813679444ee029093d2a2f38ba3cac4ed7e + checksum: 10/806fd8e3adc9157e17bf0d4a2c899cf6b98a0bbe9f453f630094ce791866271f6cddcaf2133e6513715d934fcba2014d287c7053d5d7934937b3a34d5a3d84ad languageName: node linkType: hard -"node-releases@npm:^2.0.14": - version: 2.0.14 - resolution: "node-releases@npm:2.0.14" - checksum: 10/0f7607ec7db5ef1dc616899a5f24ae90c869b6a54c2d4f36ff6d84a282ab9343c7ff3ca3670fe4669171bb1e8a9b3e286e1ef1c131f09a83d70554f855d54f24 +"node-releases@npm:^2.0.19": + version: 2.0.19 + resolution: "node-releases@npm:2.0.19" + checksum: 10/c2b33b4f0c40445aee56141f13ca692fa6805db88510e5bbb3baadb2da13e1293b738e638e15e4a8eb668bb9e97debb08e7a35409b477b5cc18f171d35a83045 languageName: node linkType: hard @@ -5698,25 +6440,14 @@ __metadata: languageName: node linkType: hard -"nopt@npm:^6.0.0": - version: 6.0.0 - resolution: "nopt@npm:6.0.0" +"nopt@npm:^8.0.0": + version: 8.1.0 + resolution: "nopt@npm:8.1.0" dependencies: - abbrev: "npm:^1.0.0" + abbrev: "npm:^3.0.0" bin: nopt: bin/nopt.js - checksum: 10/3c1128e07cd0241ae66d6e6a472170baa9f3e84dd4203950ba8df5bafac4efa2166ce917a57ef02b01ba7c40d18b2cc64b29b225fd3640791fe07b24f0b33a32 - languageName: node - linkType: hard - -"nopt@npm:~1.0.10": - version: 1.0.10 - resolution: "nopt@npm:1.0.10" - dependencies: - abbrev: "npm:1" - bin: - nopt: ./bin/nopt.js - checksum: 10/4f01ad1e144883a190d70bd6003f26e2f3a899230fe1b0f3310e43779c61cab5ae0063a9209912cd52fc4c552b266b38173853aa9abe27ecb04acbdfdca2e9fc + checksum: 10/26ab456c51a96f02a9e5aa8d1b80ef3219f2070f3f3528a040e32fb735b1e651e17bdf0f1476988d3a46d498f35c65ed662d122f340d38ce4a7e71dd7b20c4bc languageName: node linkType: hard @@ -5787,18 +6518,6 @@ __metadata: languageName: node linkType: hard -"npmlog@npm:^6.0.0": - version: 6.0.2 - resolution: "npmlog@npm:6.0.2" - dependencies: - are-we-there-yet: "npm:^3.0.0" - console-control-strings: "npm:^1.1.0" - gauge: "npm:^4.0.3" - set-blocking: "npm:^2.0.0" - checksum: 10/82b123677e62deb9e7472e27b92386c09e6e254ee6c8bcd720b3011013e4168bc7088e984f4fbd53cb6e12f8b4690e23e4fa6132689313e0d0dc4feea45489bb - languageName: node - linkType: hard - "object-assign@npm:^4": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -5817,21 +6536,14 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.7.0": - version: 1.8.0 - resolution: "object-inspect@npm:1.8.0" - checksum: 10/065e1b3e10d8bf57b0b7a9eaa949df92762a1e53af2ef799194dd974515a08de9d14c5923cb61ec5bad47663a0e26f6115294c7f976a9237eef6b086e72bf9b1 - languageName: node - linkType: hard - -"object-inspect@npm:^1.9.0": - version: 1.12.3 - resolution: "object-inspect@npm:1.12.3" - checksum: 10/532b0036f0472f561180fac0d04fe328ee01f57637624c83fb054f81b5bfe966cdf4200612a499ed391a7ca3c46b20a0bc3a55fc8241d944abe687c556a32b39 +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10/aa13b1190ad3e366f6c83ad8a16ed37a19ed57d267385aa4bfdccda833d7b90465c057ff6c55d035a6b2e52c1a2295582b294217a0a3a1ae7abdd6877ef781fb languageName: node linkType: hard -"object-keys@npm:^1.0.11, object-keys@npm:^1.0.12, object-keys@npm:^1.1.1": +"object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" checksum: 10/3d81d02674115973df0b7117628ea4110d56042e5326413e4b4313f0bcdf7dd78d4a3acef2c831463fa3796a66762c49daef306f4a0ea1af44877d7086d73bde @@ -5847,15 +6559,17 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.0": - version: 4.1.0 - resolution: "object.assign@npm:4.1.0" +"object.assign@npm:^4.1.7": + version: 4.1.7 + resolution: "object.assign@npm:4.1.7" dependencies: - define-properties: "npm:^1.1.2" - function-bind: "npm:^1.1.1" - has-symbols: "npm:^1.0.0" - object-keys: "npm:^1.0.11" - checksum: 10/9ca3797cdbd3ff8a196aaee7b4808f2d1802c4d3655b1a03d15ca0284fc1034d097c112c6be60a11a866bcbf728b05318326834054d36f11a17aacb15d04ec9e + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.3" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + has-symbols: "npm:^1.1.0" + object-keys: "npm:^1.1.1" + checksum: 10/3fe28cdd779f2a728a9a66bd688679ba231a2b16646cd1e46b528fe7c947494387dda4bc189eff3417f3717ef4f0a8f2439347cf9a9aa3cef722fbfd9f615587 languageName: node linkType: hard @@ -5902,17 +6616,28 @@ __metadata: languageName: node linkType: hard -"optionator@npm:^0.9.1": - version: 0.9.1 - resolution: "optionator@npm:0.9.1" +"optionator@npm:^0.9.3": + version: 0.9.4 + resolution: "optionator@npm:0.9.4" dependencies: deep-is: "npm:^0.1.3" fast-levenshtein: "npm:^2.0.6" levn: "npm:^0.4.1" prelude-ls: "npm:^1.2.1" type-check: "npm:^0.4.0" - word-wrap: "npm:^1.2.3" - checksum: 10/19cfb625ba3cafd99c204744595a8b5111491632d379be341a8286c53a0101adac6f7ca9be4319ccecaaf5d43a55e65dde8b434620726032472833d958d43698 + word-wrap: "npm:^1.2.5" + checksum: 10/a8398559c60aef88d7f353a4f98dcdff6090a4e70f874c827302bf1213d9106a1c4d5fcb68dacb1feb3c30a04c4102f41047aa55d4c576b863d6fc876e001af6 + languageName: node + linkType: hard + +"own-keys@npm:^1.0.1": + version: 1.0.1 + resolution: "own-keys@npm:1.0.1" + dependencies: + get-intrinsic: "npm:^1.2.6" + object-keys: "npm:^1.1.1" + safe-push-apply: "npm:^1.0.0" + checksum: 10/ab4bb3b8636908554fc19bf899e225444195092864cb61503a0d048fdaf662b04be2605b636a4ffeaf6e8811f6fcfa8cbb210ec964c0eb1a41eb853e1d5d2f41 languageName: node linkType: hard @@ -5941,12 +6666,17 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: "npm:^3.0.0" - checksum: 10/7ba4a2b1e24c05e1fc14bbaea0fc6d85cf005ae7e9c9425d4575550f37e2e584b1af97bcde78eacd7559208f20995988d52881334db16cf77bc1bcf68e48ed7c +"p-map@npm:^7.0.2": + version: 7.0.3 + resolution: "p-map@npm:7.0.3" + checksum: 10/2ef48ccfc6dd387253d71bf502604f7893ed62090b2c9d73387f10006c342606b05233da0e4f29388227b61eb5aeface6197e166520c465c234552eeab2fe633 + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10/58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 languageName: node linkType: hard @@ -6037,24 +6767,34 @@ __metadata: languageName: node linkType: hard -"path-parse@npm:^1.0.6": - version: 1.0.6 - resolution: "path-parse@npm:1.0.6" - checksum: 10/962a85dd384d68d469ec5ba4010df8f8f9b7e936ce603bbe3211476c5615feb3c2b1ca61211a78445fadc833f0b1a86ea6484c861035ec4ac93011ba9aff9a11 +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 10/49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: "npm:^10.2.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: 10/5e8845c159261adda6f09814d7725683257fcc85a18f329880ab4d7cc1d12830967eae5d5894e453f341710d5484b8fdbbd4d75181b4d6e1eb2f4dc7aeadc434 languageName: node linkType: hard -"path-to-regexp@npm:0.1.7": - version: 0.1.7 - resolution: "path-to-regexp@npm:0.1.7" - checksum: 10/701c99e1f08e3400bea4d701cf6f03517474bb1b608da71c78b1eb261415b645c5670dfae49808c89e12cea2dccd113b069f040a80de012da0400191c6dbd1c8 +"path-to-regexp@npm:0.1.12": + version: 0.1.12 + resolution: "path-to-regexp@npm:0.1.12" + checksum: 10/2e30f6a0144679c1f95c98e166b96e6acd1e72be9417830fefc8de7ac1992147eb9a4c7acaa59119fb1b3c34eec393b2129ef27e24b2054a3906fc4fb0d1398e languageName: node linkType: hard -"path-to-regexp@npm:2.2.1": - version: 2.2.1 - resolution: "path-to-regexp@npm:2.2.1" - checksum: 10/1a7125f8c1b5904d556a29722333219df4aa779039e903efe2fbfe0cc3ae9246672846fc8ad285664020b70e434347e0bc9af691fd7d61df8eaa7b018dcd56fb +"path-to-regexp@npm:3.3.0": + version: 3.3.0 + resolution: "path-to-regexp@npm:3.3.0" + checksum: 10/8d256383af8db66233ee9027cfcbf8f5a68155efbb4f55e784279d3ab206dcaee554ddb72ff0dae97dd2882af9f7fa802634bb7cffa2e796927977e31b829259 languageName: node linkType: hard @@ -6074,10 +6814,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: 10/a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 +"picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 languageName: node linkType: hard @@ -6088,6 +6828,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 10/ce617b8da36797d09c0baacb96ca8a44460452c89362d7cb8f70ca46b4158ba8bc3606912de7c818eb4a939f7f9015cef3c766ec8a0c6bfc725fdc078e39c717 + languageName: node + linkType: hard + "pidtree@npm:^0.3.0": version: 0.3.1 resolution: "pidtree@npm:0.3.1" @@ -6111,14 +6858,21 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.35": - version: 8.4.36 - resolution: "postcss@npm:8.4.36" +"possible-typed-array-names@npm:^1.0.0": + version: 1.1.0 + resolution: "possible-typed-array-names@npm:1.1.0" + checksum: 10/2f44137b8d3dd35f4a7ba7469eec1cd9cfbb46ec164b93a5bc1f4c3d68599c9910ee3b91da1d28b4560e9cc8414c3cd56fedc07259c67e52cc774476270d3302 + languageName: node + linkType: hard + +"postcss@npm:^8.4.43": + version: 8.5.3 + resolution: "postcss@npm:8.5.3" dependencies: - nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.1.0" - checksum: 10/8b8bb8e6b67ed8bd3c6773b9b7e9f5fabcf3c6bce35f08dcbea099ce971e81ed5e0639dd08edcdd7078aa78523cdd195f985dde2e070013897f8a7aa4e95adf3 + nanoid: "npm:^3.3.8" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10/6d7e21a772e8b05bf102636918654dac097bac013f0dc8346b72ac3604fc16829646f94ea862acccd8f82e910b00e2c11c1f0ea276543565d278c7ca35516a7c languageName: node linkType: hard @@ -6154,6 +6908,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^5.0.0": + version: 5.0.0 + resolution: "proc-log@npm:5.0.0" + checksum: 10/35610bdb0177d3ab5d35f8827a429fb1dc2518d9e639f2151ac9007f01a061c30e0c635a970c9b00c39102216160f6ec54b62377c92fac3b7bfc2ad4b98d195c + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -6161,13 +6922,6 @@ __metadata: languageName: node linkType: hard -"promise-inflight@npm:^1.0.1": - version: 1.0.1 - resolution: "promise-inflight@npm:1.0.1" - checksum: 10/1560d413ea20c5a74f3631d39ba8cbd1972b9228072a755d01e1f5ca5110382d9af76a1582d889445adc6e75bb5ac4886b56dc4b6eae51b30145d7bb1ac7505b - languageName: node - linkType: hard - "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -6202,33 +6956,26 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^1.3.2": - version: 1.4.1 - resolution: "punycode@npm:1.4.1" - checksum: 10/af2700dde1a116791ff8301348ff344c47d6c224e875057237d1b5112035655fb07a6175cfdb8bf0e3a8cdfd2dc82b3a622e0aefd605566c0e949a6d0d1256a4 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0": - version: 2.1.1 - resolution: "punycode@npm:2.1.1" - checksum: 10/939daa010c2cacebdb060c40ecb52fef0a739324a66f7fffe0f94353a1ee83e3b455e9032054c4a0c4977b0a28e27086f2171c392832b59a01bd948fd8e20914 +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: 10/febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059 languageName: node linkType: hard -"punycode@npm:^2.1.1": - version: 2.3.0 - resolution: "punycode@npm:2.3.0" - checksum: 10/d4e7fbb96f570c57d64b09a35a1182c879ac32833de7c6926a2c10619632c1377865af3dab5479f59d51da18bcd5035a20a5ef6ceb74020082a3e78025d9a9ca +"qs@npm:6.13.0": + version: 6.13.0 + resolution: "qs@npm:6.13.0" + dependencies: + side-channel: "npm:^1.0.6" + checksum: 10/f548b376e685553d12e461409f0d6e5c59ec7c7d76f308e2a888fd9db3e0c5e89902bedd0754db3a9038eda5f27da2331a6f019c8517dc5e0a16b3c9a6e9cef8 languageName: node linkType: hard -"qs@npm:6.11.0": - version: 6.11.0 - resolution: "qs@npm:6.11.0" - dependencies: - side-channel: "npm:^1.0.4" - checksum: 10/5a3bfea3e2f359ede1bfa5d2f0dbe54001aa55e40e27dc3e60fab814362d83a9b30758db057c2011b6f53a2d4e4e5150194b5bac45372652aecb3e3c0d4b256e +"queue-microtask@npm:^1.2.2": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: 10/72900df0616e473e824202113c3df6abae59150dfb73ed13273503127235320e9c8ca4aaaaccfd58cf417c6ca92a6e68ee9a5c3182886ae949a768639b388a7b languageName: node linkType: hard @@ -6255,15 +7002,15 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.1": - version: 2.5.1 - resolution: "raw-body@npm:2.5.1" +"raw-body@npm:2.5.2": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" dependencies: bytes: "npm:3.1.2" http-errors: "npm:2.0.0" iconv-lite: "npm:0.4.24" unpipe: "npm:1.0.0" - checksum: 10/280bedc12db3490ecd06f740bdcf66093a07535374b51331242382c0e130bb273ebb611b7bc4cba1b4b4e016cc7b1f4b05a6df885a6af39c2bc3b94c02291c84 + checksum: 10/863b5171e140546a4d99f349b720abac4410338e23df5e409cfcc3752538c9caf947ce382c89129ba976f71894bd38b5806c774edac35ebf168d02aa1ac11a95 languageName: node linkType: hard @@ -6282,30 +7029,54 @@ __metadata: linkType: hard "react-dom@npm:^18.2.0": - version: 18.2.0 - resolution: "react-dom@npm:18.2.0" + version: 18.3.1 + resolution: "react-dom@npm:18.3.1" dependencies: loose-envify: "npm:^1.1.0" - scheduler: "npm:^0.23.0" + scheduler: "npm:^0.23.2" + peerDependencies: + react: ^18.3.1 + checksum: 10/3f4b73a3aa083091173b29812b10394dd06f4ac06aff410b74702cfb3aa29d7b0ced208aab92d5272919b612e5cda21aeb1d54191848cf6e46e9e354f3541f81 + languageName: node + linkType: hard + +"react-refresh@npm:^0.17.0": + version: 0.17.0 + resolution: "react-refresh@npm:0.17.0" + checksum: 10/5e94f07d43bb1cfdc9b0c6e0c8c73e754005489950dcff1edb53aa8451d1d69a47b740b195c7c80fb4eb511c56a3585dc55eddd83f0097fb5e015116a1460467 + languageName: node + linkType: hard + +"react-router-dom@npm:^6.8.0": + version: 6.30.1 + resolution: "react-router-dom@npm:6.30.1" + dependencies: + "@remix-run/router": "npm:1.23.0" + react-router: "npm:6.30.1" peerDependencies: - react: ^18.2.0 - checksum: 10/ca5e7762ec8c17a472a3605b6f111895c9f87ac7d43a610ab7024f68cd833d08eda0625ce02ec7178cc1f3c957cf0b9273cdc17aa2cd02da87544331c43b1d21 + react: ">=16.8" + react-dom: ">=16.8" + checksum: 10/d61f04a36ca8a0a61e71bac2616f3f0d4142ced4a473d872738ca363b43d042f4d6dc249e7f7ae1c06f89599277e2fde11583d61cf6b34e999e79caf845acb37 languageName: node linkType: hard -"react-refresh@npm:^0.14.0": - version: 0.14.0 - resolution: "react-refresh@npm:0.14.0" - checksum: 10/75941262ce3ed4fc79b52492943fd59692f29b84f30f3822713b7e920f28e85c62a4386f85cbfbaea95ed62d3e74209f0a0bb065904b7ab2f166a74ac3812e2a +"react-router@npm:6.30.1": + version: 6.30.1 + resolution: "react-router@npm:6.30.1" + dependencies: + "@remix-run/router": "npm:1.23.0" + peerDependencies: + react: ">=16.8" + checksum: 10/880d6cafd6376dd1e624f6f600b7a208c4142d60eaea66241980ef57260c237b3465c3ff96b28f21ae354410345bbbb1817c3bba083012aade6626027d53506f languageName: node linkType: hard "react@npm:^18.2.0": - version: 18.2.0 - resolution: "react@npm:18.2.0" + version: 18.3.1 + resolution: "react@npm:18.3.1" dependencies: loose-envify: "npm:^1.1.0" - checksum: 10/b9214a9bd79e99d08de55f8bef2b7fc8c39630be97c4e29d7be173d14a9a10670b5325e94485f74cd8bff4966ef3c78ee53c79a7b0b9b70cba20aa8973acc694 + checksum: 10/261137d3f3993eaa2368a83110466fc0e558bc2c7f7ae7ca52d94f03aac945f45146bd85e5f481044db1758a1dbb57879e2fcdd33924e2dde1bdc550ce73f7bf languageName: node linkType: hard @@ -6335,17 +7106,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.6.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10/d9e3e53193adcdb79d8f10f2a1f6989bd4389f5936c6f8b870e77570853561c362bee69feca2bbb7b32368ce96a85504aa4cedf7cf80f36e6a9de30d64244048 - languageName: node - linkType: hard - "readdirp@npm:^2.2.1": version: 2.2.1 resolution: "readdirp@npm:2.2.1" @@ -6357,6 +7117,22 @@ __metadata: languageName: node linkType: hard +"reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.9": + version: 1.0.10 + resolution: "reflect.getprototypeof@npm:1.0.10" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.9" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.7" + get-proto: "npm:^1.0.1" + which-builtin-type: "npm:^1.2.1" + checksum: 10/80a4e2be716f4fe46a89a08ccad0863b47e8ce0f49616cab2d65dab0fbd53c6fdba0f52935fd41d37a2e4e22355c272004f920d63070de849f66eea7aeb4a081 + languageName: node + linkType: hard + "regex-not@npm:^1.0.0, regex-not@npm:^1.0.2": version: 1.0.2 resolution: "regex-not@npm:1.0.2" @@ -6367,6 +7143,20 @@ __metadata: languageName: node linkType: hard +"regexp.prototype.flags@npm:^1.5.4": + version: 1.5.4 + resolution: "regexp.prototype.flags@npm:1.5.4" + dependencies: + call-bind: "npm:^1.0.8" + define-properties: "npm:^1.2.1" + es-errors: "npm:^1.3.0" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + set-function-name: "npm:^2.0.2" + checksum: 10/8ab897ca445968e0b96f6237641510f3243e59c180ee2ee8d83889c52ff735dd1bf3657fcd36db053e35e1d823dd53f2565d0b8021ea282c9fe62401c6c3bd6d + languageName: node + linkType: hard + "registry-auth-token@npm:3.3.2": version: 3.3.2 resolution: "registry-auth-token@npm:3.3.2" @@ -6439,20 +7229,28 @@ __metadata: linkType: hard "resolve@npm:^1.10.0": - version: 1.17.0 - resolution: "resolve@npm:1.17.0" + version: 1.22.10 + resolution: "resolve@npm:1.22.10" dependencies: - path-parse: "npm:^1.0.6" - checksum: 10/74141da8c56192fd46f6aa887864f8fd74c1755425174526610cb775177278bb414c6f6feb3051ccd73d774d2ae124c6c97e463e30d7ffd9a87f7da202b851dd + is-core-module: "npm:^2.16.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/0a398b44da5c05e6e421d70108822c327675febb880eebe905587628de401854c61d5df02866ff34fc4cb1173a51c9f0e84a94702738df3611a62e2acdc68181 languageName: node linkType: hard "resolve@patch:resolve@npm%3A^1.10.0#optional!builtin": - version: 1.17.0 - resolution: "resolve@patch:resolve@npm%3A1.17.0#optional!builtin::version=1.17.0&hash=c3c19d" + version: 1.22.10 + resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" dependencies: - path-parse: "npm:^1.0.6" - checksum: 10/02e87fe9233d169fdc5220572c7b8933c9e23323aaecfd5b8d0b106a7f09dc676dd4d380e66c72b1369489292bcb337b13aad28b480a1bde5a5c040ff16758ea + is-core-module: "npm:^2.16.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10/d4d878bfe3702d215ea23e75e0e9caf99468e3db76f5ca100d27ebdc527366fee3877e54bce7d47cc72ca8952fc2782a070d238bfa79a550eeb0082384c3b81a languageName: node linkType: hard @@ -6471,9 +7269,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10/14222c9e1d3f9ae01480c50d96057228a8524706db79cdeb5a2ce5bb7070dd9f409a6f84a02cbef8cdc80d39aef86f2dd03d155188a1300c599b05437dcd2ffb + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 10/af47851b547e8a8dc89af144fceee17b80d5beaf5e6f57ed086432d79943434ff67ca526e92275be6f54b6189f6920a24eace75c2657eed32d02c400312b21ec languageName: node linkType: hard @@ -6488,24 +7286,31 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.2.0": - version: 4.13.0 - resolution: "rollup@npm:4.13.0" - dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.13.0" - "@rollup/rollup-android-arm64": "npm:4.13.0" - "@rollup/rollup-darwin-arm64": "npm:4.13.0" - "@rollup/rollup-darwin-x64": "npm:4.13.0" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.13.0" - "@rollup/rollup-linux-arm64-gnu": "npm:4.13.0" - "@rollup/rollup-linux-arm64-musl": "npm:4.13.0" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.13.0" - "@rollup/rollup-linux-x64-gnu": "npm:4.13.0" - "@rollup/rollup-linux-x64-musl": "npm:4.13.0" - "@rollup/rollup-win32-arm64-msvc": "npm:4.13.0" - "@rollup/rollup-win32-ia32-msvc": "npm:4.13.0" - "@rollup/rollup-win32-x64-msvc": "npm:4.13.0" - "@types/estree": "npm:1.0.5" +"rollup@npm:^4.20.0": + version: 4.41.1 + resolution: "rollup@npm:4.41.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.41.1" + "@rollup/rollup-android-arm64": "npm:4.41.1" + "@rollup/rollup-darwin-arm64": "npm:4.41.1" + "@rollup/rollup-darwin-x64": "npm:4.41.1" + "@rollup/rollup-freebsd-arm64": "npm:4.41.1" + "@rollup/rollup-freebsd-x64": "npm:4.41.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.41.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.41.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.41.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.41.1" + "@rollup/rollup-linux-loongarch64-gnu": "npm:4.41.1" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.41.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.41.1" + "@rollup/rollup-linux-riscv64-musl": "npm:4.41.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.41.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.41.1" + "@rollup/rollup-linux-x64-musl": "npm:4.41.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.41.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.41.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.41.1" + "@types/estree": "npm:1.0.7" fsevents: "npm:~2.3.2" dependenciesMeta: "@rollup/rollup-android-arm-eabi": @@ -6516,14 +7321,28 @@ __metadata: optional: true "@rollup/rollup-darwin-x64": optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true "@rollup/rollup-linux-arm-gnueabihf": optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true "@rollup/rollup-linux-arm64-gnu": optional: true "@rollup/rollup-linux-arm64-musl": optional: true + "@rollup/rollup-linux-loongarch64-gnu": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true "@rollup/rollup-linux-riscv64-gnu": optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true "@rollup/rollup-linux-x64-gnu": optional: true "@rollup/rollup-linux-x64-musl": @@ -6538,14 +7357,29 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 10/3ebced8ad49e8b5617cb7013cb106dd8ac99ae31a71f9689dc689b8fdaf0eb109f3d861330ef659e5f28a2c38e040282aea0e1df150b165f53f649d46275df84 + checksum: 10/b7b5a5668bc05445766b1b7342475d9dbb173925e806805720bcfad277a591c5452f11fe1f1fd9f8030b4e52f093610a10200599258ad5faad9104944b984c36 languageName: node linkType: hard "run-parallel@npm:^1.1.9": - version: 1.1.9 - resolution: "run-parallel@npm:1.1.9" - checksum: 10/8bbeda89c2c1dbfeaa0cdb9f17e93a011ac58ef77339ef1e61a62208b67c8e7b661891df677bb7c5be84b8792e27061177368d500b3c731bb019b0c71e667591 + version: 1.2.0 + resolution: "run-parallel@npm:1.2.0" + dependencies: + queue-microtask: "npm:^1.2.2" + checksum: 10/cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d + languageName: node + linkType: hard + +"safe-array-concat@npm:^1.1.3": + version: 1.1.3 + resolution: "safe-array-concat@npm:1.1.3" + dependencies: + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.2" + get-intrinsic: "npm:^1.2.6" + has-symbols: "npm:^1.1.0" + isarray: "npm:^2.0.5" + checksum: 10/fac4f40f20a3f7da024b54792fcc61059e814566dcbb04586bfefef4d3b942b2408933f25b7b3dd024affd3f2a6bbc916bef04807855e4f192413941369db864 languageName: node linkType: hard @@ -6556,13 +7390,34 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 languageName: node linkType: hard +"safe-push-apply@npm:^1.0.0": + version: 1.0.0 + resolution: "safe-push-apply@npm:1.0.0" + dependencies: + es-errors: "npm:^1.3.0" + isarray: "npm:^2.0.5" + checksum: 10/2bd4e53b6694f7134b9cf93631480e7fafc8637165f0ee91d5a4af5e7f33d37de9562d1af5021178dd4217d0230cde8d6530fa28cfa1ebff9a431bf8fff124b4 + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.1.0": + version: 1.1.0 + resolution: "safe-regex-test@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + is-regex: "npm:^1.2.1" + checksum: 10/ebdb61f305bf4756a5b023ad86067df5a11b26898573afe9e52a548a63c3bd594825d9b0e2dde2eb3c94e57e0e04ac9929d4107c394f7b8e56a4613bed46c69a + languageName: node + linkType: hard + "safe-regex@npm:^1.1.0": version: 1.1.0 resolution: "safe-regex@npm:1.1.0" @@ -6579,21 +7434,12 @@ __metadata: languageName: node linkType: hard -"saslprep@npm:^1.0.3": - version: 1.0.3 - resolution: "saslprep@npm:1.0.3" - dependencies: - sparse-bitfield: "npm:^3.0.3" - checksum: 10/d6cae5f0adc960f355b7a78c25616c2aea31e7eeb6322eb2d553f09f1db249594651c1e5d54910e9a47b1dc6131beda82db13ffafbceea92f2a673d69c839982 - languageName: node - linkType: hard - -"scheduler@npm:^0.23.0": - version: 0.23.0 - resolution: "scheduler@npm:0.23.0" +"scheduler@npm:^0.23.2": + version: 0.23.2 + resolution: "scheduler@npm:0.23.2" dependencies: loose-envify: "npm:^1.1.0" - checksum: 10/0c4557aa37bafca44ff21dc0ea7c92e2dbcb298bc62eae92b29a39b029134f02fb23917d6ebc8b1fa536b4184934314c20d8864d156a9f6357f3398aaf7bfda8 + checksum: 10/e8d68b89d18d5b028223edf090092846868a765a591944760942b77ea1f69b17235f7e956696efbb62c8130ab90af7e0949bfb8eba7896335507317236966bc9 languageName: node linkType: hard @@ -6614,11 +7460,11 @@ __metadata: linkType: hard "semver@npm:2 || 3 || 4 || 5, semver@npm:^5.0.3, semver@npm:^5.1.0, semver@npm:^5.5.0": - version: 5.7.1 - resolution: "semver@npm:5.7.1" + version: 5.7.2 + resolution: "semver@npm:5.7.2" bin: - semver: ./bin/semver - checksum: 10/fbc71cf00736480ca0dd67f2527cda6e0fde5447af00bd2ce06cb522d510216603a63ed0c6c87d8904507c1a4e8113e628a71424ebd9e0fd7d345ee8ed249690 + semver: bin/semver + checksum: 10/fca14418a174d4b4ef1fecb32c5941e3412d52a4d3d85165924ce3a47fbc7073372c26faf7484ceb4bbc2bde25880c6b97e492473dc7e9708fdfb1c6a02d546e languageName: node linkType: hard @@ -6632,19 +7478,17 @@ __metadata: linkType: hard "semver@npm:^7.3.5, semver@npm:^7.3.7": - version: 7.5.1 - resolution: "semver@npm:7.5.1" - dependencies: - lru-cache: "npm:^6.0.0" + version: 7.7.2 + resolution: "semver@npm:7.7.2" bin: semver: bin/semver.js - checksum: 10/01fcb5ff66fb8cb9ff54e898ac9786fbafec65f93d0df910ea9300451719b204b1c5e8007c99c1abb410eb60f84497a1f8c02b1a0e97880842b7f6075e1d82b6 + checksum: 10/7a24cffcaa13f53c09ce55e05efe25cd41328730b2308678624f8b9f5fc3093fc4d189f47950f0b811ff8f3c3039c24a2c36717ba7961615c682045bf03e1dda languageName: node linkType: hard -"send@npm:0.18.0": - version: 0.18.0 - resolution: "send@npm:0.18.0" +"send@npm:0.19.0": + version: 0.19.0 + resolution: "send@npm:0.19.0" dependencies: debug: "npm:2.6.9" depd: "npm:2.0.0" @@ -6659,44 +7503,43 @@ __metadata: on-finished: "npm:2.4.1" range-parser: "npm:~1.2.1" statuses: "npm:2.0.1" - checksum: 10/ec66c0ad109680ad8141d507677cfd8b4e40b9559de23191871803ed241718e99026faa46c398dcfb9250676076573bd6bfe5d0ec347f88f4b7b8533d1d391cb + checksum: 10/1f6064dea0ae4cbe4878437aedc9270c33f2a6650a77b56a16b62d057527f2766d96ee282997dd53ec0339082f2aad935bc7d989b46b48c82fc610800dc3a1d0 languageName: node linkType: hard -"serve-handler@npm:6.1.5": - version: 6.1.5 - resolution: "serve-handler@npm:6.1.5" +"serve-handler@npm:6.1.6": + version: 6.1.6 + resolution: "serve-handler@npm:6.1.6" dependencies: bytes: "npm:3.0.0" content-disposition: "npm:0.5.2" - fast-url-parser: "npm:1.1.3" mime-types: "npm:2.1.18" minimatch: "npm:3.1.2" path-is-inside: "npm:1.0.2" - path-to-regexp: "npm:2.2.1" + path-to-regexp: "npm:3.3.0" range-parser: "npm:1.2.0" - checksum: 10/cab6f381d380ae77ae6da017b5c7b1c25d8f0bed00cf509a18bc768c1830a0043ce53668390ad8a84366e47b353b3f1f7c9d10c7167886179f2e89cb95243a90 + checksum: 10/7e7d93eb7e69fcd9f9c5afc2ef2b46cb0072b4af13cbabef9bca725afb350ddae6857d8c8be2c256f7ce1f7677c20347801399c11caa5805c0090339f894e8f2 languageName: node linkType: hard -"serve-static@npm:1.15.0": - version: 1.15.0 - resolution: "serve-static@npm:1.15.0" +"serve-static@npm:1.16.2": + version: 1.16.2 + resolution: "serve-static@npm:1.16.2" dependencies: - encodeurl: "npm:~1.0.2" + encodeurl: "npm:~2.0.0" escape-html: "npm:~1.0.3" parseurl: "npm:~1.3.3" - send: "npm:0.18.0" - checksum: 10/699b2d4c29807a51d9b5e0f24955346911437aebb0178b3c4833ad30d3eca93385ff9927254f5c16da345903cad39d9cd4a532198c95a5129cc4ed43911b15a4 + send: "npm:0.19.0" + checksum: 10/7fa9d9c68090f6289976b34fc13c50ac8cd7f16ae6bce08d16459300f7fc61fbc2d7ebfa02884c073ec9d6ab9e7e704c89561882bbe338e99fcacb2912fde737 languageName: node linkType: hard "serve@npm:^14.2.0": - version: 14.2.0 - resolution: "serve@npm:14.2.0" + version: 14.2.4 + resolution: "serve@npm:14.2.4" dependencies: - "@zeit/schemas": "npm:2.29.0" - ajv: "npm:8.11.0" + "@zeit/schemas": "npm:2.36.0" + ajv: "npm:8.12.0" arg: "npm:5.0.2" boxen: "npm:7.0.0" chalk: "npm:5.0.1" @@ -6704,18 +7547,48 @@ __metadata: clipboardy: "npm:3.0.0" compression: "npm:1.7.4" is-port-reachable: "npm:4.0.0" - serve-handler: "npm:6.1.5" + serve-handler: "npm:6.1.6" update-check: "npm:1.5.4" bin: serve: build/main.js - checksum: 10/0fcc61d73b6b8f3d21eec690905d3843b4d0b27bbc552a8a998467bb4a40711e96b1164577560fb9023625e51d50d93011d2ca67966a16c86169addc913776ef + checksum: 10/79627f399226b765f6e2f0f62faeceda5db17d00f40f9ad9faa39049729ea4ce7b595a72cc0dba3543947288772cb60f2b0ab91efa3bbedfe644ca7ee0484df1 languageName: node linkType: hard -"set-blocking@npm:^2.0.0": - version: 2.0.0 - resolution: "set-blocking@npm:2.0.0" - checksum: 10/8980ebf7ae9eb945bb036b6e283c547ee783a1ad557a82babf758a065e2fb6ea337fd82cac30dd565c1e606e423f30024a19fff7afbf4977d784720c4026a8ef +"set-function-length@npm:^1.2.2": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.4" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.2" + checksum: 10/505d62b8e088468917ca4e3f8f39d0e29f9a563b97dbebf92f4bd2c3172ccfb3c5b8e4566d5fcd00784a00433900e7cb8fbc404e2dbd8c3818ba05bb9d4a8a6d + languageName: node + linkType: hard + +"set-function-name@npm:^2.0.2": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" + dependencies: + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" + functions-have-names: "npm:^1.2.3" + has-property-descriptors: "npm:^1.0.2" + checksum: 10/c7614154a53ebf8c0428a6c40a3b0b47dac30587c1a19703d1b75f003803f73cdfa6a93474a9ba678fa565ef5fbddc2fae79bca03b7d22ab5fd5163dbe571a74 + languageName: node + linkType: hard + +"set-proto@npm:^1.0.0": + version: 1.0.0 + resolution: "set-proto@npm:1.0.0" + dependencies: + dunder-proto: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.0.0" + checksum: 10/b87f8187bca595ddc3c0721ece4635015fd9d7cb294e6dd2e394ce5186a71bbfa4dc8a35010958c65e43ad83cde09642660e61a952883c24fd6b45ead15f045c languageName: node linkType: hard @@ -6771,37 +7644,74 @@ __metadata: linkType: hard "shell-quote@npm:^1.6.1": - version: 1.7.2 - resolution: "shell-quote@npm:1.7.2" - checksum: 10/5d7540d320ee5acb5a1d5ca3163d5706fbe055cc4e0adf6f1f85ef8f54c55b453c492d125c450f20d9bec223dcac9df4c74510b4ea3ff4c24f15f7d848a0fc4c + version: 1.8.2 + resolution: "shell-quote@npm:1.8.2" + checksum: 10/3ae4804fd80a12ba07650d0262804ae3b479a62a6b6971a6dc5fa12995507aa63d3de3e6a8b7a8d18f4ce6eb118b7d75db7fcb2c0acbf016f210f746b10cfe02 languageName: node linkType: hard -"side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" +"side-channel-list@npm:^1.0.0": + version: 1.0.0 + resolution: "side-channel-list@npm:1.0.0" dependencies: - call-bind: "npm:^1.0.0" - get-intrinsic: "npm:^1.0.2" - object-inspect: "npm:^1.9.0" - checksum: 10/c4998d9fc530b0e75a7fd791ad868fdc42846f072734f9080ff55cc8dc7d3899abcda24fd896aa6648c3ab7021b4bb478073eb4f44dfd55bce9714bc1a7c5d45 + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + checksum: 10/603b928997abd21c5a5f02ae6b9cc36b72e3176ad6827fab0417ead74580cc4fb4d5c7d0a8a2ff4ead34d0f9e35701ed7a41853dac8a6d1a664fcce1a044f86f languageName: node linkType: hard -"signal-exit@npm:^3.0.0": - version: 3.0.3 - resolution: "signal-exit@npm:3.0.3" - checksum: 10/f0169d3f1263d06df32ca072b0bf33b34c6f8f0341a7a1621558a2444dfbe8f5fec76b35537fcc6f0bc4944bdb5336fe0bdcf41a5422c4e45a1dba3f45475e6c +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10/5771861f77feefe44f6195ed077a9e4f389acc188f895f570d56445e251b861754b547ea9ef73ecee4e01fdada6568bfe9020d2ec2dfc5571e9fa1bbc4a10615 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10/a815c89bc78c5723c714ea1a77c938377ea710af20d4fb886d362b0d1f8ac73a17816a5f6640f354017d7e292a43da9c5e876c22145bac00b76cfb3468001736 + languageName: node + linkType: hard + +"side-channel@npm:^1.0.6, side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + side-channel-list: "npm:^1.0.0" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10/7d53b9db292c6262f326b6ff3bc1611db84ece36c2c7dc0e937954c13c73185b0406c56589e2bb8d071d6fee468e14c39fb5d203ee39be66b7b8174f179afaba languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: 10/a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 languageName: node linkType: hard +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 10/c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f + languageName: node + linkType: hard + "simplex-noise@npm:^2.4.0": version: 2.4.0 resolution: "simplex-noise@npm:2.4.0" @@ -6859,31 +7769,31 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "socks-proxy-agent@npm:7.0.0" +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" dependencies: - agent-base: "npm:^6.0.2" - debug: "npm:^4.3.3" - socks: "npm:^2.6.2" - checksum: 10/26c75d9c62a9ed3fd494df60e65e88da442f78e0d4bc19bfd85ac37bd2c67470d6d4bba5202e804561cda6674db52864c9e2a2266775f879bc8d89c1445a5f4c + agent-base: "npm:^7.1.2" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10/ee99e1dacab0985b52cbe5a75640be6e604135e9489ebdc3048635d186012fbaecc20fbbe04b177dee434c319ba20f09b3e7dfefb7d932466c0d707744eac05c languageName: node linkType: hard -"socks@npm:^2.6.2, socks@npm:^2.7.1": - version: 2.7.1 - resolution: "socks@npm:2.7.1" +"socks@npm:^2.7.1, socks@npm:^2.8.3": + version: 2.8.4 + resolution: "socks@npm:2.8.4" dependencies: - ip: "npm:^2.0.0" + ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 10/5074f7d6a13b3155fa655191df1c7e7a48ce3234b8ccf99afa2ccb56591c195e75e8bb78486f8e9ea8168e95a29573cbaad55b2b5e195160ae4d2ea6811ba833 + checksum: 10/ab3af97aeb162f32c80e176c717ccf16a11a6ebb4656a62b94c0f96495ea2a1f4a8206c04b54438558485d83d0c5f61920c07a1a5d3963892a589b40cc6107dd languageName: node linkType: hard -"source-map-js@npm:^1.1.0": - version: 1.1.0 - resolution: "source-map-js@npm:1.1.0" - checksum: 10/6319690f50f8da9445433d7edfb8cc4ffd42b9deb69739c73bb65992c61dfdf6f5979f49d4a25e85e51ebf235fde65e061291e8ee2a68da2b87a38c62cb4aef4 +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 languageName: node linkType: hard @@ -6924,19 +7834,19 @@ __metadata: linkType: hard "spdx-correct@npm:^3.0.0": - version: 3.1.1 - resolution: "spdx-correct@npm:3.1.1" + version: 3.2.0 + resolution: "spdx-correct@npm:3.2.0" dependencies: spdx-expression-parse: "npm:^3.0.0" spdx-license-ids: "npm:^3.0.0" - checksum: 10/688e028c3ca6090d1b516272a2dd60b30f163cbf166295ac4b8078fd74f524365cd996e2b18cabdaa41647aa806e117604aa3b3216f69076a554999913d09d47 + checksum: 10/cc2e4dbef822f6d12142116557d63f5facf3300e92a6bd24e907e4865e17b7e1abd0ee6b67f305cae6790fc2194175a24dc394bfcc01eea84e2bdad728e9ae9a languageName: node linkType: hard "spdx-exceptions@npm:^2.1.0": - version: 2.3.0 - resolution: "spdx-exceptions@npm:2.3.0" - checksum: 10/cb69a26fa3b46305637123cd37c85f75610e8c477b6476fa7354eb67c08128d159f1d36715f19be6f9daf4b680337deb8c65acdcae7f2608ba51931540687ac0 + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: 10/bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15 languageName: node linkType: hard @@ -6951,9 +7861,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.5 - resolution: "spdx-license-ids@npm:3.0.5" - checksum: 10/a5b78b6765826db9a98c890588e474fadb06dfaecc7b579b545ccc11f0a9739f097d11d741c1e0302562884f5d6e3ce0008ca68fa0036646831e0e61331b85b0 + version: 3.0.21 + resolution: "spdx-license-ids@npm:3.0.21" + checksum: 10/17a033b4c3485f081fc9faa1729dde8782a85d9131b156f2397c71256c2e1663132857d3cba1457c4965f179a4dcf1b69458a31e9d3d0c766d057ef0e3a0b4f2 languageName: node linkType: hard @@ -6966,12 +7876,19 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^9.0.0": - version: 9.0.1 - resolution: "ssri@npm:9.0.1" +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10/e7587128c423f7e43cc625fe2f87e6affdf5ca51c1cc468e910d8aaca46bb44a7fbcfa552f787b1d3987f7043aeb4527d1b99559e6621e01b42b3f45e5a24cbb + languageName: node + linkType: hard + +"ssri@npm:^12.0.0": + version: 12.0.0 + resolution: "ssri@npm:12.0.0" dependencies: - minipass: "npm:^3.1.1" - checksum: 10/7638a61e91432510718e9265d48d0438a17d53065e5184f1336f234ef6aa3479663942e41e97df56cda06bb24d9d0b5ef342c10685add3cac7267a82d7fa6718 + minipass: "npm:^7.0.3" + checksum: 10/7024c1a6e39b3f18aa8f1c8290e884fe91b0f9ca5a6c6d410544daad54de0ba664db879afe16412e187c6c292fd60b937f047ee44292e5c2af2dcc6d8e1a9b48 languageName: node linkType: hard @@ -6992,7 +7909,7 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -7025,41 +7942,52 @@ __metadata: linkType: hard "string.prototype.padend@npm:^3.0.0": - version: 3.1.0 - resolution: "string.prototype.padend@npm:3.1.0" + version: 3.1.6 + resolution: "string.prototype.padend@npm:3.1.6" dependencies: - define-properties: "npm:^1.1.3" - es-abstract: "npm:^1.17.0-next.1" - checksum: 10/22981a2aa20010c6322f02e83d66c502af8d690d070865e4b0c9fd8f7daf706100382f11865702f66e977666fc1afd7a4c2da6f23e8c15d0841f236a6f7c4ba4 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.2" + es-object-atoms: "npm:^1.0.0" + checksum: 10/52cebc58a0252ef45dd0fec3ee4e8655bcc8b6c07b4956c5965542316f5ab3a38ca8d1d06e9804979828fba9de61e59294fe23f64e5d413ac40963a4d4969c19 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.1": - version: 1.0.1 - resolution: "string.prototype.trimend@npm:1.0.1" +"string.prototype.trim@npm:^1.2.10": + version: 1.2.10 + resolution: "string.prototype.trim@npm:1.2.10" dependencies: - define-properties: "npm:^1.1.3" - es-abstract: "npm:^1.17.5" - checksum: 10/e4e2c21f0145a6fa8c111b1bee6075d509a40702611329bcebd7ffc5cc13562cfa99636faeacccbea306d01c023dc763ce0cf38cf5d7b654705b74847b0f0e57 + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.2" + define-data-property: "npm:^1.1.4" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.23.5" + es-object-atoms: "npm:^1.0.0" + has-property-descriptors: "npm:^1.0.2" + checksum: 10/47bb63cd2470a64bc5e2da1e570d369c016ccaa85c918c3a8bb4ab5965120f35e66d1f85ea544496fac84b9207a6b722adf007e6c548acd0813e5f8a82f9712a languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.1": - version: 1.0.1 - resolution: "string.prototype.trimstart@npm:1.0.1" +"string.prototype.trimend@npm:^1.0.9": + version: 1.0.9 + resolution: "string.prototype.trimend@npm:1.0.9" dependencies: - define-properties: "npm:^1.1.3" - es-abstract: "npm:^1.17.5" - checksum: 10/0fe3cad8d597a418b058b6ec2d5c48b73172c71cb60089a0a38373eb3c2d501c4d9a00bbfad90e581c2ecf136f10f85a9dc664390e059b805dae9e4707465e0f + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.2" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/140c73899b6747de9e499c7c2e7a83d549c47a26fa06045b69492be9cfb9e2a95187499a373983a08a115ecff8bc3bd7b0fb09b8ff72fb2172abe766849272ef languageName: node linkType: hard -"string_decoder@npm:^1.1.1": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" dependencies: - safe-buffer: "npm:~5.2.0" - checksum: 10/54d23f4a6acae0e93f999a585e673be9e561b65cd4cca37714af1e893ab8cd8dfa52a9e4f58f48f87b4a44918d3a9254326cb80ed194bf2e4c226e2b21767e56 + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10/160167dfbd68e6f7cb9f51a16074eebfce1571656fc31d40c3738ca9e30e35496f2c046fe57b6ad49f65f238a152be8c86fd9a2dd58682b5eba39dad995b3674 languageName: node linkType: hard @@ -7072,6 +8000,15 @@ __metadata: languageName: node linkType: hard +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 10/ae3b5436d34fadeb6096367626ce987057713c566e1e7768818797e00ac5d62023d0f198c4e681eae9e20701721980b26a64a8f5b91238869592a9c6800719a2 + languageName: node + linkType: hard + "strip-ansi@npm:^4.0.0": version: 4.0.0 resolution: "strip-ansi@npm:4.0.0" @@ -7081,15 +8018,6 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10/ae3b5436d34fadeb6096367626ce987057713c566e1e7768818797e00ac5d62023d0f198c4e681eae9e20701721980b26a64a8f5b91238869592a9c6800719a2 - languageName: node - linkType: hard - "strip-ansi@npm:^7.0.1": version: 7.1.0 resolution: "strip-ansi@npm:7.1.0" @@ -7120,7 +8048,7 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": +"strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" checksum: 10/492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 @@ -7135,9 +8063,9 @@ __metadata: linkType: hard "strnum@npm:^1.0.5": - version: 1.0.5 - resolution: "strnum@npm:1.0.5" - checksum: 10/d3117975db8372d4d7b2c07601ed2f65bf21cc48d741f37a8617b76370d228f2ec26336e53791ebc3638264d23ca54e6c241f57f8c69bd4941c63c79440525ca + version: 1.1.2 + resolution: "strnum@npm:1.1.2" + checksum: 10/ccd6297a1fdaf0fc8ea0ea904acdae76878d49a4b0d98a70155df4bc081fd88eac5ec99fb150f3d1d1af065c1898d38420705259ba6c39aa850c671bcd54e35d languageName: node linkType: hard @@ -7159,17 +8087,38 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.1.15 - resolution: "tar@npm:6.1.15" +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 10/a9dc19ae2220c952bd2231d08ddeecb1b0328b61e72071ff4000c8384e145cc07c1c0bdb3b5a1cb06e186a7b2790f1dee793418b332f6ddf320de25d9125be7e + languageName: node + linkType: hard + +"tailwindcss@npm:4.1.7, tailwindcss@npm:^4.1.7": + version: 4.1.7 + resolution: "tailwindcss@npm:4.1.7" + checksum: 10/c229ed1e0cfe83b431581e462e18175ee0c0d75344710cd844cbcab28df118270695a2cd545868e6013ef2e5f4c4b619fb84cd3b5e21f80b8908d3ac74f67a5d + languageName: node + linkType: hard + +"tapable@npm:^2.2.0": + version: 2.2.2 + resolution: "tapable@npm:2.2.2" + checksum: 10/065a0dc44aba1b32020faa1c27c719e8f76e5345347515d8494bf158524f36e9f22ad9eaa5b5494f9d5d67bf0640afdd5698505948c46d720b6b7e69d19349a6 + languageName: node + linkType: hard + +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" dependencies: - chownr: "npm:^2.0.0" - fs-minipass: "npm:^2.0.0" - minipass: "npm:^5.0.0" - minizlib: "npm:^2.1.1" - mkdirp: "npm:^1.0.3" - yallist: "npm:^4.0.0" - checksum: 10/4848b92da8581e64ce4d8a760b47468dd9d212a4612846d8dd75b5c224a42c66ed5bcf8cfa9e9cd2eb64ebe1351413fb3eac93324a4eee536f0941beefa1f2eb + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10/12a2a4fc6dee23e07cc47f1aeb3a14a1afd3f16397e1350036a8f4cdfee8dcac7ef5978337a4e7b2ac2c27a9a6d46388fc2088ea7c80cb6878c814b1425f8ecf languageName: node linkType: hard @@ -7196,10 +8145,13 @@ __metadata: languageName: node linkType: hard -"to-fast-properties@npm:^2.0.0": - version: 2.0.0 - resolution: "to-fast-properties@npm:2.0.0" - checksum: 10/be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 +"tinyglobby@npm:^0.2.12": + version: 0.2.13 + resolution: "tinyglobby@npm:0.2.13" + dependencies: + fdir: "npm:^6.4.4" + picomatch: "npm:^4.0.2" + checksum: 10/b04557ee58ad2be5f2d2cbb4b441476436c92bb45ba2e1fc464d686b793392b305ed0bcb8b877429e9b5036bdd46770c161a08384c0720b6682b7cd6ac80e403 languageName: node linkType: hard @@ -7251,13 +8203,11 @@ __metadata: linkType: hard "touch@npm:^3.1.0": - version: 3.1.0 - resolution: "touch@npm:3.1.0" - dependencies: - nopt: "npm:~1.0.10" + version: 3.1.1 + resolution: "touch@npm:3.1.1" bin: - nodetouch: ./bin/nodetouch.js - checksum: 10/ece1d9693fbc9b73d8a6d902537b787b5685ac1aeab7562857c50e6671415a73c985055393442b518f4ac37b85c3e7a3e6c36af71142fed13b8bb04fb6664936 + nodetouch: bin/nodetouch.js + checksum: 10/853e763a1f4903302c5654ed353f84ad85baf757dac62c2d37ab67e0477cfd271e8c64771fcfad42310aff7c9d284ddb435ee5ca13ff36d0f3693fedd8e971d1 languageName: node linkType: hard @@ -7270,24 +8220,26 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^1.11.1": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: 10/7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb +"tr46@npm:^5.1.0": + version: 5.1.1 + resolution: "tr46@npm:5.1.1" + dependencies: + punycode: "npm:^2.3.1" + checksum: 10/833a0e1044574da5790148fd17866d4ddaea89e022de50279967bcd6b28b4ce0d30d59eb3acf9702b60918975b3bad481400337e3a2e6326cffa5c77b874753d languageName: node linkType: hard "tslib@npm:^1.8.1": - version: 1.13.0 - resolution: "tslib@npm:1.13.0" - checksum: 10/703f52fe8437e3aa3f85f8811dced64c99eb44b6d67cb84acacf64d68fbabedae23b429973af3b4872f497b4b497f5b2019a479666ef1cb8e5b71c8c3862687f + version: 1.14.1 + resolution: "tslib@npm:1.14.1" + checksum: 10/7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb languageName: node linkType: hard -"tslib@npm:^2.3.1, tslib@npm:^2.5.0": - version: 2.5.3 - resolution: "tslib@npm:2.5.3" - checksum: 10/d507e60ebe2480af4efc1655dfdb2762bb6ca57d76c4ba680375af801493648c2e97808bbd7e54691eb40e33a7e2e793cdef9c24ce6a8539b03cac8b26e09a61 +"tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.8.0": + version: 2.8.1 + resolution: "tslib@npm:2.8.1" + checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 languageName: node linkType: hard @@ -7341,23 +8293,88 @@ __metadata: languageName: node linkType: hard +"typed-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-buffer@npm:1.0.3" + dependencies: + call-bound: "npm:^1.0.3" + es-errors: "npm:^1.3.0" + is-typed-array: "npm:^1.1.14" + checksum: 10/3fb91f0735fb413b2bbaaca9fabe7b8fc14a3fa5a5a7546bab8a57e755be0e3788d893195ad9c2b842620592de0e68d4c077d4c2c41f04ec25b8b5bb82fa9a80 + languageName: node + linkType: hard + +"typed-array-byte-length@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-byte-length@npm:1.0.3" + dependencies: + call-bind: "npm:^1.0.8" + for-each: "npm:^0.3.3" + gopd: "npm:^1.2.0" + has-proto: "npm:^1.2.0" + is-typed-array: "npm:^1.1.14" + checksum: 10/269dad101dda73e3110117a9b84db86f0b5c07dad3a9418116fd38d580cab7fc628a4fc167e29b6d7c39da2f53374b78e7cb578b3c5ec7a556689d985d193519 + languageName: node + linkType: hard + +"typed-array-byte-offset@npm:^1.0.4": + version: 1.0.4 + resolution: "typed-array-byte-offset@npm:1.0.4" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + for-each: "npm:^0.3.3" + gopd: "npm:^1.2.0" + has-proto: "npm:^1.2.0" + is-typed-array: "npm:^1.1.15" + reflect.getprototypeof: "npm:^1.0.9" + checksum: 10/c2869aa584cdae24ecfd282f20a0f556b13a49a9d5bca1713370bb3c89dff0ccbc5ceb45cb5b784c98f4579e5e3e2a07e438c3a5b8294583e2bd4abbd5104fb5 + languageName: node + linkType: hard + +"typed-array-length@npm:^1.0.7": + version: 1.0.7 + resolution: "typed-array-length@npm:1.0.7" + dependencies: + call-bind: "npm:^1.0.7" + for-each: "npm:^0.3.3" + gopd: "npm:^1.0.1" + is-typed-array: "npm:^1.1.13" + possible-typed-array-names: "npm:^1.0.0" + reflect.getprototypeof: "npm:^1.0.6" + checksum: 10/d6b2f0e81161682d2726eb92b1dc2b0890890f9930f33f9bcf6fc7272895ce66bc368066d273e6677776de167608adc53fcf81f1be39a146d64b630edbf2081c + languageName: node + linkType: hard + "typescript@npm:^5.5.3": - version: 5.5.3 - resolution: "typescript@npm:5.5.3" + version: 5.8.3 + resolution: "typescript@npm:5.8.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/11a867312419ed497929aafd2f1d28b2cd41810a5eb6c6e9e169559112e9ea073d681c121a29102e67cd4478d0a4ae37a306a5800f3717f59c4337e6a9bd5e8d + checksum: 10/65c40944c51b513b0172c6710ee62e951b70af6f75d5a5da745cb7fab132c09ae27ffdf7838996e3ed603bb015dadd099006658046941bd0ba30340cc563ae92 languageName: node linkType: hard "typescript@patch:typescript@npm%3A^5.5.3#optional!builtin": - version: 5.5.3 - resolution: "typescript@patch:typescript@npm%3A5.5.3#optional!builtin::version=5.5.3&hash=379a07" + version: 5.8.3 + resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=379a07" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/7cf7acb78a80f749b82842f2ffe01e90e7b3e709a6f4268588e0b7599c41dca1059be217f47778fe1a380bfaf60933021ef20d002c426d4d7745e1b36c11467b + checksum: 10/98470634034ec37fd9ea61cc82dcf9a27950d0117a4646146b767d085a2ec14b137aae9642a83d1c62732d7fdcdac19bb6288b0bb468a72f7a06ae4e1d2c72c9 + languageName: node + linkType: hard + +"unbox-primitive@npm:^1.1.0": + version: 1.1.0 + resolution: "unbox-primitive@npm:1.1.0" + dependencies: + call-bound: "npm:^1.0.3" + has-bigints: "npm:^1.0.2" + has-symbols: "npm:^1.1.0" + which-boxed-primitive: "npm:^1.1.1" + checksum: 10/fadb347020f66b2c8aeacf8b9a79826fa34cc5e5457af4eb0bbc4e79bd87fed0fa795949825df534320f7c13f199259516ad30abc55a6e7b91d8d996ca069e50 languageName: node linkType: hard @@ -7368,6 +8385,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.21.0": + version: 6.21.0 + resolution: "undici-types@npm:6.21.0" + checksum: 10/ec8f41aa4359d50f9b59fa61fe3efce3477cc681908c8f84354d8567bb3701fafdddf36ef6bff307024d3feb42c837cf6f670314ba37fc8145e219560e473d14 + languageName: node + linkType: hard + "union-value@npm:^1.0.0": version: 1.0.1 resolution: "union-value@npm:1.0.1" @@ -7380,21 +8404,21 @@ __metadata: languageName: node linkType: hard -"unique-filename@npm:^2.0.0": - version: 2.0.1 - resolution: "unique-filename@npm:2.0.1" +"unique-filename@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-filename@npm:4.0.0" dependencies: - unique-slug: "npm:^3.0.0" - checksum: 10/807acf3381aff319086b64dc7125a9a37c09c44af7620bd4f7f3247fcd5565660ac12d8b80534dcbfd067e6fe88a67e621386dd796a8af828d1337a8420a255f + unique-slug: "npm:^5.0.0" + checksum: 10/6a62094fcac286b9ec39edbd1f8f64ff92383baa430af303dfed1ffda5e47a08a6b316408554abfddd9730c78b6106bef4ca4d02c1231a735ddd56ced77573df languageName: node linkType: hard -"unique-slug@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-slug@npm:3.0.0" +"unique-slug@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-slug@npm:5.0.0" dependencies: imurmurhash: "npm:^0.1.4" - checksum: 10/26fc5bc209a875956dd5e84ca39b89bc3be777b112504667c35c861f9547df95afc80439358d836b878b6d91f6ee21fe5ba1a966e9ec2e9f071ddf3fd67d45ee + checksum: 10/beafdf3d6f44990e0a5ce560f8f881b4ee811be70b6ba0db25298c31c8cf525ed963572b48cd03be1c1349084f9e339be4241666d7cf1ebdad20598d3c652b27 languageName: node linkType: hard @@ -7438,17 +8462,17 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.13": - version: 1.0.13 - resolution: "update-browserslist-db@npm:1.0.13" +"update-browserslist-db@npm:^1.1.3": + version: 1.1.3 + resolution: "update-browserslist-db@npm:1.1.3" dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" + escalade: "npm:^3.2.0" + picocolors: "npm:^1.1.1" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10/9074b4ef34d2ed931f27d390aafdd391ee7c45ad83c508e8fed6aaae1eb68f81999a768ed8525c6f88d4001a4fbf1b8c0268f099d0e8e72088ec5945ac796acf + checksum: 10/87af2776054ffb9194cf95e0201547d041f72ee44ce54b144da110e65ea7ca01379367407ba21de5c9edd52c74d95395366790de67f3eb4cc4afa0fe4424e76f languageName: node linkType: hard @@ -7481,11 +8505,11 @@ __metadata: linkType: hard "uri-js@npm:^4.2.2": - version: 4.2.2 - resolution: "uri-js@npm:4.2.2" + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" dependencies: punycode: "npm:^2.1.0" - checksum: 10/e9499d30bfa7559acc255ab196bf7be0db9e5e5550cc0dfd8aeaeabbe423c323b18e261b31b996a409465b29f6ad814f8683f0c4f476ee347a57103dba0fb7f7 + checksum: 10/b271ca7e3d46b7160222e3afa3e531505161c9a4e097febae9664e4b59912f4cbe94861361a4175edac3a03fee99d91e44b6a58c17a634bc5a664b19fc76fbcb languageName: node linkType: hard @@ -7512,7 +8536,7 @@ __metadata: languageName: node linkType: hard -"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": +"util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" checksum: 10/474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 @@ -7526,12 +8550,12 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^8.3.2": - version: 8.3.2 - resolution: "uuid@npm:8.3.2" +"uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "uuid@npm:10.0.0" bin: uuid: dist/bin/uuid - checksum: 10/9a5f7aa1d6f56dd1e8d5f2478f855f25c645e64e26e347a98e98d95781d5ed20062d6cca2eecb58ba7c84bc3910be95c0451ef4161906abaab44f9cb68ffbdd1 + checksum: 10/35aa60614811a201ff90f8ca5e9ecb7076a75c3821e17f0f5ff72d44e36c2d35fcbc2ceee9c4ac7317f4cc41895da30e74f3885e30313bee48fda6338f250538 languageName: node linkType: hard @@ -7562,40 +8586,41 @@ __metadata: linkType: hard "vite-plugin-top-level-await@npm:^1.4.1": - version: 1.4.1 - resolution: "vite-plugin-top-level-await@npm:1.4.1" + version: 1.5.0 + resolution: "vite-plugin-top-level-await@npm:1.5.0" dependencies: "@rollup/plugin-virtual": "npm:^3.0.2" - "@swc/core": "npm:^1.3.100" - uuid: "npm:^9.0.1" + "@swc/core": "npm:^1.10.16" + uuid: "npm:^10.0.0" peerDependencies: vite: ">=2.8" - checksum: 10/68c82f5fa2e860ebe0867337ced237042127a03ec367cfeadb890dc20f623811263bac59a1afeac8b9ac7c11501752ded03cd035ac75c35d20531a7e42f096a7 + checksum: 10/d6875a20ba57d2f72616f41e35bf97477e1494a6185a21b054f0b08101347f78378b63d9866d46dca402d09c71cec7f4ef7584b6524bb178435ea627ea16da4d languageName: node linkType: hard "vite-plugin-wasm@npm:^3.3.0": - version: 3.3.0 - resolution: "vite-plugin-wasm@npm:3.3.0" + version: 3.4.1 + resolution: "vite-plugin-wasm@npm:3.4.1" peerDependencies: - vite: ^2 || ^3 || ^4 || ^5 - checksum: 10/1bcfb50f03280f1966247a4bf9e6ab3a4a76a26fa58fd178708cb3758629cffea544a13c87d0982de0a95a4b41bfc2ad46ae51d3b22080eec965ebfaa17e0454 + vite: ^2 || ^3 || ^4 || ^5 || ^6 + checksum: 10/4329318a6ece0e4021e89d83738bbe9214e85f93fd8cfe3a9026fcf46cf5fe9d921a37c1ef2f9c726c753e4ace203c575edfb10a14adf817b885a307c0cbb10c languageName: node linkType: hard "vite@npm:^5.1.6": - version: 5.1.6 - resolution: "vite@npm:5.1.6" + version: 5.4.19 + resolution: "vite@npm:5.4.19" dependencies: - esbuild: "npm:^0.19.3" + esbuild: "npm:^0.21.3" fsevents: "npm:~2.3.3" - postcss: "npm:^8.4.35" - rollup: "npm:^4.2.0" + postcss: "npm:^8.4.43" + rollup: "npm:^4.20.0" peerDependencies: "@types/node": ^18.0.0 || >=20.0.0 less: "*" lightningcss: ^1.21.0 sass: "*" + sass-embedded: "*" stylus: "*" sugarss: "*" terser: ^5.4.0 @@ -7611,6 +8636,8 @@ __metadata: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: @@ -7619,7 +8646,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10/f48073e93ead62fa58034398442de4517c824b3e50184f8b4059fb24077a26f2c04e910e29d7fb7ec51ea53eb61b9c7d94d56b14a38851de80c67480094cc79d + checksum: 10/27900c87ec6f84967ba12bd4a24c2b9182c3ddad278a13a1c7736ccc4ac7e325f3fbdc11836e2906857140cc89c55121cb0746d4100046e797e21e1e7570d9c4 languageName: node linkType: hard @@ -7640,6 +8667,77 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^14.1.0 || ^13.0.0": + version: 14.2.0 + resolution: "whatwg-url@npm:14.2.0" + dependencies: + tr46: "npm:^5.1.0" + webidl-conversions: "npm:^7.0.0" + checksum: 10/f0a95b0601c64f417c471536a2d828b4c16fe37c13662483a32f02f183ed0f441616609b0663fb791e524e8cd56d9a86dd7366b1fc5356048ccb09b576495e7c + languageName: node + linkType: hard + +"which-boxed-primitive@npm:^1.1.0, which-boxed-primitive@npm:^1.1.1": + version: 1.1.1 + resolution: "which-boxed-primitive@npm:1.1.1" + dependencies: + is-bigint: "npm:^1.1.0" + is-boolean-object: "npm:^1.2.1" + is-number-object: "npm:^1.1.1" + is-string: "npm:^1.1.1" + is-symbol: "npm:^1.1.1" + checksum: 10/a877c0667bc089518c83ad4d845cf8296b03efe3565c1de1940c646e00a2a1ae9ed8a185bcfa27cbf352de7906f0616d83b9d2f19ca500ee02a551fb5cf40740 + languageName: node + linkType: hard + +"which-builtin-type@npm:^1.2.1": + version: 1.2.1 + resolution: "which-builtin-type@npm:1.2.1" + dependencies: + call-bound: "npm:^1.0.2" + function.prototype.name: "npm:^1.1.6" + has-tostringtag: "npm:^1.0.2" + is-async-function: "npm:^2.0.0" + is-date-object: "npm:^1.1.0" + is-finalizationregistry: "npm:^1.1.0" + is-generator-function: "npm:^1.0.10" + is-regex: "npm:^1.2.1" + is-weakref: "npm:^1.0.2" + isarray: "npm:^2.0.5" + which-boxed-primitive: "npm:^1.1.0" + which-collection: "npm:^1.0.2" + which-typed-array: "npm:^1.1.16" + checksum: 10/22c81c5cb7a896c5171742cd30c90d992ff13fb1ea7693e6cf80af077791613fb3f89aa9b4b7f890bd47b6ce09c6322c409932359580a2a2a54057f7b52d1cbe + languageName: node + linkType: hard + +"which-collection@npm:^1.0.2": + version: 1.0.2 + resolution: "which-collection@npm:1.0.2" + dependencies: + is-map: "npm:^2.0.3" + is-set: "npm:^2.0.3" + is-weakmap: "npm:^2.0.2" + is-weakset: "npm:^2.0.3" + checksum: 10/674bf659b9bcfe4055f08634b48a8588e879161b9fefed57e9ec4ff5601e4d50a05ccd76cf10f698ef5873784e5df3223336d56c7ce88e13bcf52ebe582fc8d7 + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.19": + version: 1.1.19 + resolution: "which-typed-array@npm:1.1.19" + dependencies: + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" + for-each: "npm:^0.3.5" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-tostringtag: "npm:^1.0.2" + checksum: 10/12be30fb88567f9863186bee1777f11bea09dd59ed8b3ce4afa7dd5cade75e2f4cc56191a2da165113cc7cf79987ba021dac1e22b5b62aa7e5c56949f2469a68 + languageName: node + linkType: hard + "which@npm:^1.2.9": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -7651,7 +8749,7 @@ __metadata: languageName: node linkType: hard -"which@npm:^2.0.1, which@npm:^2.0.2": +"which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -7662,12 +8760,14 @@ __metadata: languageName: node linkType: hard -"wide-align@npm:^1.1.5": - version: 1.1.5 - resolution: "wide-align@npm:1.1.5" +"which@npm:^5.0.0": + version: 5.0.0 + resolution: "which@npm:5.0.0" dependencies: - string-width: "npm:^1.0.2 || 2 || 3 || 4" - checksum: 10/d5f8027b9a8255a493a94e4ec1b74a27bff6679d5ffe29316a3215e4712945c84ef73ca4045c7e20ae7d0c72f5f57f296e04a4928e773d4276a2f1222e4c2e99 + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10/6ec99e89ba32c7e748b8a3144e64bfc74aa63e2b2eacbb61a0060ad0b961eb1a632b08fb1de067ed59b002cec3e21de18299216ebf2325ef0f78e0f121e14e90 languageName: node linkType: hard @@ -7689,14 +8789,25 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:^1.2.3": - version: 1.2.3 - resolution: "word-wrap@npm:1.2.3" - checksum: 10/08a677e1578b9cc367a03d52bc51b6869fec06303f68d29439e4ed647257411f857469990c31066c1874678937dac737c9f8f20d3fd59918fb86b7d926a76b15 +"word-wrap@npm:^1.2.5": + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: 10/1ec6f6089f205f83037be10d0c4b34c9183b0b63fca0834a5b3cee55dd321429d73d40bb44c8fc8471b5203d6e8f8275717f49a8ff4b2b0ab41d7e1b563e0854 + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10/cebdaeca3a6880da410f75209e68cd05428580de5ad24535f22696d7d9cab134d1f8498599f344c3cf0fb37c1715807a183778d8c648d6cc0cb5ff2bb4236540 languageName: node linkType: hard -"wrap-ansi@npm:^8.0.1": +"wrap-ansi@npm:^8.0.1, wrap-ansi@npm:^8.1.0": version: 8.1.0 resolution: "wrap-ansi@npm:8.1.0" dependencies: @@ -7726,8 +8837,8 @@ __metadata: linkType: hard "ws@npm:^8.8.0": - version: 8.13.0 - resolution: "ws@npm:8.13.0" + version: 8.18.2 + resolution: "ws@npm:8.18.2" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -7736,7 +8847,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/1769532b6fdab9ff659f0b17810e7501831d34ecca23fd179ee64091dd93a51f42c59f6c7bb4c7a384b6c229aca8076fb312aa35626257c18081511ef62a161d + checksum: 10/018e04ec95561d88248d53a2eaf094b4ae131e9b062f2679e6e8a62f04649bc543448f1e038125225ac6bbb25f54c1e65d7a2cc9dbc1e28b43e5e6b7162ad88e languageName: node linkType: hard @@ -7768,6 +8879,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10/1884d272d485845ad04759a255c71775db0fac56308764b4c77ea56a20d56679fad340213054c8c9c9c26fcfd4c4b2a90df993b7e0aaf3cdb73c618d1d1a802a + languageName: node + linkType: hard + "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0"