diff --git a/config/webpack.config.js b/config/webpack.config.js index f69f979..37cf856 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -293,6 +293,9 @@ module.exports = function (webpackEnv) { ], }, resolve: { + // fallback: { + // buffer: require.resolve("buffer/") + // }, // This allows you to set a fallback for where webpack should look for modules. // We placed these paths second because we want `node_modules` to "win" // if there are any conflicts. This matches Node resolution mechanism. @@ -321,6 +324,11 @@ module.exports = function (webpackEnv) { ...(modules.webpackAliases || {}), }, plugins: [ + // Work around for Buffer is undefined: + // https://github.com/webpack/changelog-v5/issues/10 + // new webpack.ProvidePlugin({ + // Buffer: ['buffer', 'Buffer'], + // }), // Prevents users from importing files from outside of src/ (or node_modules/). // This often causes confusion because we only process files within src/ with babel. // To fix this, we prevent you from importing files out of src/ -- if you'd like to, diff --git a/package-lock.json b/package-lock.json index f069320..68c3f25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "babel-preset-react-app": "^10.0.1", "bfj": "^7.0.2", "browserslist": "^4.18.1", + "buffer": "^6.0.3", "camelcase": "^6.2.1", "case-sensitive-paths-webpack-plugin": "^2.4.0", "clsx": "^1.1.1", @@ -5001,6 +5002,25 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -5173,6 +5193,29 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -8466,6 +8509,25 @@ "node": ">=4" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -19657,6 +19719,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -19793,6 +19860,15 @@ "node-int64": "^0.4.0" } }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -22161,6 +22237,11 @@ "harmony-reflect": "^1.4.6" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", diff --git a/package.json b/package.json index db69065..2d59ff3 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "babel-preset-react-app": "^10.0.1", "bfj": "^7.0.2", "browserslist": "^4.18.1", + "buffer": "^6.0.3", "camelcase": "^6.2.1", "case-sensitive-paths-webpack-plugin": "^2.4.0", "clsx": "^1.1.1", diff --git a/src/App.tsx b/src/App.tsx index cbd6655..ed9cb64 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,9 @@ import { ItemStack as ISC } from './components/ItemStack'; import { ItemStack, ItemType } from 'core/ItemStack'; import { DisplayPane } from 'surfaces/DisplayPane'; import { Item } from 'core/Item'; +import { deserialzeCommands, serializeCommands } from 'core/serialize'; + +const Buffer = require("buffer/").Buffer; export const App: React.FC = () => { const [commands, setCommands] = useState([ @@ -62,7 +65,15 @@ export const App: React.FC = () => { } }, [commands, displayIndex]); + // useEffect(()=>{ + // const encoded = serializeCommands(commands); + // console.log(encoded); + // const deserialized = deserialzeCommands(encoded); + // console.log(deserialized); + // window.location.hash = "#"+encoded; + // }, [commands]); + return (
@@ -107,18 +118,21 @@ export const App: React.FC = () => {
- + {displayIndex >= 0 && displayIndex < commands.length && { - const arrCopy = [...commands]; - arrCopy[displayIndex] = c; - setCommands(arrCopy); - }}/> + displayIndex={displayIndex} + command={commands[displayIndex].getDisplayString()} + stacks={inventories[displayIndex].getSlots()} + numBroken={inventories[displayIndex].getNumBroken()} + editCommand={(c)=>{ + const arrCopy = [...commands]; + arrCopy[displayIndex] = c; + setCommands(arrCopy); + }}/> + + } + { contextMenuShowing &&
{ { if(confirm("Delete?")){ setCommands(commands.filter((_,i)=>i!==contextIndex)); + if(displayIndex >= commands.length){ + setDisplayIndex(commands.length-1); + } setContextMenuShowing(false); setContextIndex(-1); } diff --git a/src/core/Command.ts b/src/core/Command.ts index 410dc1f..8bf7fd4 100644 --- a/src/core/Command.ts +++ b/src/core/Command.ts @@ -1,17 +1,31 @@ import { Inventory } from "./Inventory"; -import { Item } from "./Item"; -import { ItemStack } from "./ItemStack"; +import { Item, ItemIds } from "./Item"; +import { ItemStack, ItemType } from "./ItemStack"; + +const Buffer = require("buffer/").Buffer; export interface Command { execute(inv: Inventory): void, getDisplayString(): string, + fromBuffer(buf: Buffer): number, + toBuffer(): Buffer, } export class CommandNothing implements Command { - + static Op = 0x0; constructor(){ } + + fromBuffer(buf: Buffer): number { + return 0; + } + toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1); + buf.writeInt8(CommandNothing.Op); + return buf; + } + execute(inv: Inventory): void { } @@ -22,10 +36,47 @@ export class CommandNothing implements Command { } export class CommandInitialize implements Command { + static Op = 0x1; private stacks: ItemStack[] constructor(stacks: ItemStack[]){ this.stacks = stacks; } + public fromBuffer(buf: Buffer): number { + let read = 0; + const size = buf.readUInt16LE(); + read+=2; + const stacks: ItemStack[] = []; + for(let i=0;i{ + console.log(count); + buf.writeInt16LE(count&0xffff, write); + write+=2; + buf.writeInt8(ItemIds[item], write); + write++; + }); + return buf; + } + public execute(inv: Inventory): void { inv.init(this.stacks); } @@ -37,13 +88,25 @@ export class CommandInitialize implements Command { }) return parts.join(" "); } + } export class CommandBreakSlots implements Command { + static Op = 0x2; private numToBreak: number; constructor(numToBreak: number){ this.numToBreak = numToBreak; } + public fromBuffer(buf: Buffer): number { + this.numToBreak = buf.readInt16LE(); + return 2; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(3); + buf.writeUInt8(CommandBreakSlots.Op); + buf.writeInt16LE(this.numToBreak, 1); + return buf; + } public execute(inv: Inventory): void { inv.addBrokenSlots(this.numToBreak); } @@ -53,6 +116,15 @@ export class CommandBreakSlots implements Command { } export class CommandSave implements Command { + static Op = 0x3; + public fromBuffer(buf: Buffer): number { + return 0; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1); + buf.writeInt8(CommandSave.Op); + return buf; + } public execute(inv: Inventory): void { inv.save(); } @@ -62,6 +134,15 @@ export class CommandSave implements Command { } export class CommandReload implements Command { + static Op = 0x4; + public fromBuffer(buf: Buffer): number { + return 0; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1); + buf.writeInt8(CommandReload.Op); + return buf; + } public execute(inv: Inventory): void { inv.reload(); } @@ -71,6 +152,15 @@ export class CommandReload implements Command { } export class CommandSortKey implements Command { + static Op = 0x5; + public fromBuffer(buf: Buffer): number { + return 0; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1); + buf.writeInt8(CommandSortKey.Op); + return buf; + } public execute(inv: Inventory): void { inv.sortKey(); } @@ -80,6 +170,15 @@ export class CommandSortKey implements Command { } export class CommandSortMaterial implements Command { + static Op = 0x6; + public fromBuffer(buf: Buffer): number { + return 0; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1); + buf.writeInt8(CommandSortMaterial.Op); + return buf; + } public execute(inv: Inventory): void { inv.sortMaterial(); } @@ -88,55 +187,155 @@ export class CommandSortMaterial implements Command { } } +const Verbs = ["?", "Remove", "Drop", "Sell", "Eat", "Cook", "Get", "Add", "Pickup"]; +const VerbToId = { + "Remove" : 1, + "Drop": 2, + "Sell": 3, + "Eat": 4, + "Cook": 5, + "Get": 6, + "Add": 7, + "Pickup": 8 +} + export class CommandRemoveMaterial implements Command { - private verb: string; + static Op = 0x7; + private verb: number; private count: number; private item: Item; private slot: number; constructor(verb: string, count: number, item: Item, slot: number){ - this.verb = verb; + this.verb = VerbToId[verb as keyof typeof VerbToId] || 0; this.count = count; this.item = item; this.slot = slot; } + public fromBuffer(buf: Buffer): number { + let read = 0; + this.count = buf.readInt16LE(read); + read+=2; + const id = buf.readInt8(read); + read+=1; + for(const item in ItemIds){ + if(ItemIds[item as Item] === id){ + this.item = item as Item; + } + } + this.slot = buf.readInt16LE(read); + read+=2; + this.verb = buf.readInt8(read); + read++; + return read; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1+2+1+2+1); + let write = 0; + buf.writeInt8(CommandRemoveMaterial.Op); + write++; + buf.writeInt16LE(this.count, write); + write+=2; + buf.writeInt8(ItemIds[this.item], write); + write++; + buf.writeInt16LE(this.slot, write); + write+=2; + buf.writeInt8(this.verb, write); + return buf; + } public execute(inv: Inventory): void { inv.remove(this.item, this.count, this.slot); } public getDisplayString(): string { - return `${this.verb} ${this.count} ${this.item} From Slot ${this.slot+1}`; + return `${Verbs[this.verb]} ${this.count} ${this.item} From Slot ${this.slot+1}`; } } export class CommandRemoveUnstackableMaterial implements Command { - private verb: string; + static Op = 0x8; + private verb: number; private item: Item; private slot: number; constructor(verb: string,item: Item, slot: number){ - this.verb = verb; + this.verb = VerbToId[verb as keyof typeof VerbToId] || 0;; this.item = item; this.slot = slot; } + public fromBuffer(buf: Buffer): number { + let read = 0; + const id = buf.readInt8(read); + read+=1; + for(const item in ItemIds){ + if(ItemIds[item as Item] === id){ + this.item = item as Item; + } + } + this.slot = buf.readInt16LE(read); + read+=2; + this.verb = buf.readInt8(read); + read++; + return read; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1+1+2+1); + let write = 0; + buf.writeInt8(CommandRemoveUnstackableMaterial.Op); + write++; + buf.writeInt8(ItemIds[this.item], write); + write++; + buf.writeInt16LE(this.slot, write); + write+=2; + buf.writeInt8(this.verb, write); + return buf; + } public execute(inv: Inventory): void { inv.remove(this.item, 1, this.slot); } public getDisplayString(): string { - return `${this.verb} ${this.item} From Slot ${this.slot+1}`; + return `${Verbs[this.verb]} ${this.item} From Slot ${this.slot+1}`; } } export class CommandAddMaterial implements Command { - private verb: string; + static Op = 0x9; + private verb: number; private count: number; private item: Item; constructor(verb: string, count: number, item: Item){ - this.verb = verb; + this.verb = VerbToId[verb as keyof typeof VerbToId] || 0; this.count = count; this.item = item; } + public fromBuffer(buf: Buffer): number { + let read = 0; + const id = buf.readInt8(read); + read+=1; + for(const item in ItemIds){ + if(ItemIds[item as Item] === id){ + this.item = item as Item; + } + } + this.count = buf.readInt16LE(read); + read+=2; + this.verb = buf.readInt8(read); + read++; + return read; + } + public toBuffer(): Buffer { + const buf: Buffer = Buffer.alloc(1+1+2+1); + let write = 0; + buf.writeInt8(CommandAddMaterial.Op); + write++; + buf.writeInt8(ItemIds[this.item], write); + write++; + buf.writeInt16LE(this.count, write); + write+=2; + buf.writeInt8(this.verb, write); + return buf; + } public execute(inv: Inventory): void { inv.add(this.item, this.count); } public getDisplayString(): string { - return `${this.verb} ${this.count} ${this.item}`; + return `${Verbs[this.verb]} ${this.count} ${this.item}`; } } diff --git a/src/core/Inventory.ts b/src/core/Inventory.ts index a7563ed..23c1488 100644 --- a/src/core/Inventory.ts +++ b/src/core/Inventory.ts @@ -34,8 +34,8 @@ export class Inventory { } public init(stacks: ItemStack[]) { - this.savedSlots = [...stacks]; - this.slots = [...stacks]; + this.savedSlots = [...stacks.map((stack)=>({...stack}))]; + this.slots = [...stacks.map((stack)=>({...stack}))]; } public addBrokenSlots(num: number) { diff --git a/src/core/Item.ts b/src/core/Item.ts index a29dad1..b3dd407 100644 --- a/src/core/Item.ts +++ b/src/core/Item.ts @@ -33,6 +33,23 @@ export const ItemIds = { [Item.SpiritOrb]: 0x02, [Item.Diamond]: 0x10, + [Item.Lotus]: 0x11, + [Item.SilentPrincess]: 0x12, + [Item.Honey]: 0x13, + [Item.Acorn]: 0x14, + [Item.FaroshScale]: 0x15, + [Item.FaroshClaw]: 0x16, + [Item.FaroshHorn]: 0x17, + [Item.HeartyBass]: 0x18, + [Item.Beetle]: 0x19, + [Item.Opal]: 0x1a, + [Item.Tail]: 0x1b, + [Item.Spring]: 0x1c, + [Item.Shaft]: 0x1d, + [Item.Core]: 0x1e, + [Item.Wood]: 0x1f, + + [Item.SpeedFood]: 0x40, } export const itemToType = (item: Item): ItemType => { diff --git a/src/core/serialize.ts b/src/core/serialize.ts new file mode 100644 index 0000000..834bf62 --- /dev/null +++ b/src/core/serialize.ts @@ -0,0 +1,65 @@ +import { Command, CommandAddMaterial, CommandBreakSlots, CommandInitialize, CommandNothing, CommandReload, CommandRemoveMaterial, CommandRemoveUnstackableMaterial, CommandSave, CommandSortKey, CommandSortMaterial } from "./Command"; +import { Item } from "./Item"; + +const Buffer = require("buffer/").Buffer; + +export const serializeCommands = (commands: Command[]): string => { + const sizeBuf: Buffer = Buffer.alloc(4); + sizeBuf.writeInt32LE(commands.length); + + const commandBuffers = commands.map(c=>c.toBuffer()); + const allBufs = Buffer.concat([sizeBuf, ...commandBuffers]); + console.log(allBufs); + return allBufs.toString("base64"); +} + +export const deserialzeCommands = (base64str: string): Command[] => { + const buf: Buffer = Buffer.from(base64str, "base64"); + const size = buf.readInt32LE(); + let off = 4; + const commands: Command[] = []; + for(let i=0;i