diff --git a/src/Enums.ts b/src/Enums.ts
index d38f0727c..de46e6828 100644
--- a/src/Enums.ts
+++ b/src/Enums.ts
@@ -9,6 +9,7 @@ export * from "./Faction/Enums";
export * from "./Literature/Enums";
export * from "./Locations/Enums";
export * from "./Message/Enums";
+export * from "./Myrian/Enums";
export * from "./Programs/Enums";
export * from "./StockMarket/Enums";
export * from "./ui/Enums";
diff --git a/src/Myrian/Enums.ts b/src/Myrian/Enums.ts
new file mode 100644
index 000000000..bcb55b263
--- /dev/null
+++ b/src/Myrian/Enums.ts
@@ -0,0 +1,3 @@
+export enum MyrianActions {
+ MOVE = "MOVE",
+}
diff --git a/src/Myrian/Myrian.ts b/src/Myrian/Myrian.ts
index 5d793cd75..063882ecf 100644
--- a/src/Myrian/Myrian.ts
+++ b/src/Myrian/Myrian.ts
@@ -1,7 +1,7 @@
import { SleeveMyrianWork } from "../PersonObjects/Sleeve/Work/SleeveMyrianWork";
-import { DefaultWorld } from "./World";
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
import { Player } from "@player";
+import { DefaultWorld } from "./World";
interface MyrianSleeve {
index: number;
@@ -38,7 +38,8 @@ export class Myrian {
/** Initializes a Myrian object from a JSON save state. */
static fromJSON(value: IReviverValue): Myrian {
- return Generic_fromJSON(Myrian, value.data);
+ const v = Generic_fromJSON(Myrian, value.data);
+ return v;
}
}
diff --git a/src/Myrian/World.ts b/src/Myrian/World.ts
index 5d8ff114e..4e7de875d 100644
--- a/src/Myrian/World.ts
+++ b/src/Myrian/World.ts
@@ -1,12 +1,38 @@
-const e = ''; // empty
-const c = 'c'; // core
-const b = 'b'; // battery
-const d = 'd'; // depleted
+const e = " "; // empty
+const c = "c"; // core
+const b = "b"; // battery
+const d = "d"; // depleted
-export const DefaultWorld = [
- [b, b, b, b, b],
- [e, e, e, e, e],
- [e, e, c, e, e],
- [e, e, e, e, e],
- [b, b, b, d, d],
-];
\ No newline at end of file
+const raw = `
+
+ mmmmmmm
+ mmmmmmmm
+ mmmmmmmmmmmm
+ bbbb mmmmm
+ mmmm
+ c mmmm
+ mmmm
+ ddddd mmmm
+
+ mmmmmmmmmm
+ mmmmmmmm
+ mmmmmmmm mmmm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+
+export const DefaultWorld = raw.split("\n").map((l) => l.split(""));
+console.log(DefaultWorld);
diff --git a/src/Myrian/ui/MyrianRoot.tsx b/src/Myrian/ui/MyrianRoot.tsx
index a58420682..873899a4c 100644
--- a/src/Myrian/ui/MyrianRoot.tsx
+++ b/src/Myrian/ui/MyrianRoot.tsx
@@ -7,6 +7,7 @@ import PersonIcon from "@mui/icons-material/Person";
import BatteryFullIcon from "@mui/icons-material/BatteryFull";
import Battery20Icon from "@mui/icons-material/Battery20";
import FavoriteIcon from "@mui/icons-material/Favorite";
+import LandscapeIcon from "@mui/icons-material/Landscape";
const iterator = (i: number): number[] => {
return Array(i).fill(0);
@@ -26,17 +27,20 @@ const Cell = ({ tile }: ICellProps): React.ReactElement => {
return (
- {tile === "" &&
}
+ {tile === " " &&
}
{tile === "b" &&
}
{tile === "d" &&
}
{tile === "c" &&
}
{tile === "s" &&
}
+ {tile === "m" &&
}
);
};
@@ -49,7 +53,7 @@ export function MyrianRoot({ myrian }: IProps): React.ReactElement {
const [, setRerender] = useState(false);
const rerender = () => setRerender((old) => !old);
useEffect(() => {
- const intervalID = setInterval(rerender, 200);
+ const intervalID = setInterval(rerender, 20);
return () => clearInterval(intervalID);
}, []);
diff --git a/src/Myrian/world.txt b/src/Myrian/world.txt
new file mode 100644
index 000000000..4baa940ba
--- /dev/null
+++ b/src/Myrian/world.txt
@@ -0,0 +1,30 @@
+
+
+ mmmmmmm
+ mmmmmmmm
+ mmmmmmmmmmmm
+ bbbb mmmmm
+ mmmm
+ c mmmm
+ mmmm
+ ddddd mmmm
+
+ mmmmmmmmmm
+ mmmmmmmm
+ mmmmmmmm mmmm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts
index f021c7ca3..5b2e761ab 100644
--- a/src/Netscript/RamCostGenerator.ts
+++ b/src/Netscript/RamCostGenerator.ts
@@ -1,9 +1,23 @@
import { Player } from "@player";
-import { NSFull } from "../NetscriptFunctions";
+import { NS } from "@nsdefs";
+import { INetscriptExtra } from "../NetscriptFunctions/Extra";
+
+// Made with the help of this question
+// https://stackoverflow.com/questions/76723668/how-to-make-a-typescript-utility-type-representing-only-the-functions-of-an-obje?noredirect=1#comment135264239_76723668
+type EmptyObjToNever = {} extends T ? never : T;
+
+type PickFuncs = T extends Function
+ ? T
+ : T extends readonly any[]
+ ? never
+ : T extends object
+ ? EmptyObjToNever<{ [K in keyof T as PickFuncs extends never ? never : K]: PickFuncs }>
+ : never;
-/** The API does not include enums, args, or pid. */
export type RamCostTree = {
- [key in keyof API]: API[key] extends () => unknown ? number | (() => number) : RamCostTree;
+ [key in keyof PickFuncs]: PickFuncs[key] extends () => unknown
+ ? number | (() => number)
+ : RamCostTree[key]>;
};
/** Constants for assigning costs to ns functions */
@@ -326,15 +340,16 @@ const stanek = {
} as const;
const myr = {
- ianUse: 5.9,
- ianMove: 3.4,
+ ianAct: 5.9,
+ ianGetTile: 1.4,
+ ianWorldSize: 3.333,
+ ianGetSleeve: 2,
ianGetTask: 1.1,
ianCancelTask: 1.2,
ianEnter: 0.2,
ianLeave: 0.2,
- ianDeploy: 4.1,
ianApplyPowerup: 10.9,
-};
+} as const;
// UI API
const ui = {
@@ -424,7 +439,7 @@ const corporation = {
* An error will be generated if there are missing OR additional ram costs defined.
* To avoid errors, define every function in NetscriptDefinition.d.ts and NetscriptFunctions,
* and have a ram cost associated here. */
-export const RamCosts: RamCostTree = {
+export const RamCosts: RamCostTree = {
corporation,
hacknet,
stock,
diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts
index 446cb3e5c..a45e4d531 100644
--- a/src/NetscriptFunctions.ts
+++ b/src/NetscriptFunctions.ts
@@ -24,6 +24,7 @@ import {
LocationName,
ToastVariant,
UniversityClassType,
+ MyrianActions,
} from "@enums";
import { PromptEvent } from "./ui/React/PromptManager";
import { GetServer, DeleteServer, AddToAllServers, createUniqueRandomIp } from "./Server/AllServers";
@@ -112,6 +113,7 @@ export const enums: NSEnums = {
LocationName,
ToastVariant,
UniversityClassType,
+ MyrianActions,
};
for (const val of Object.values(enums)) Object.freeze(val);
Object.freeze(enums);
diff --git a/src/NetscriptFunctions/Myrian.ts b/src/NetscriptFunctions/Myrian.ts
index 8334fa286..3f0cde52a 100644
--- a/src/NetscriptFunctions/Myrian.ts
+++ b/src/NetscriptFunctions/Myrian.ts
@@ -1,28 +1,56 @@
import { Myr as IMyrian } from "@nsdefs";
-import { InternalAPI } from "src/Netscript/APIWrapper";
+import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers";
import { Player as player } from "../Player";
import { myrian } from "../Myrian/Helpers";
+import { MyrianActions } from "@enums";
+
+const move = (ctx: NetscriptContext, id: number, x: number, y: number) => {
+ if (!player.sleeves[id]) throw new Error(`No sleeve with index ${id}`);
+ const myrSleeve = myrian.sleeves.find((s) => s.index === id);
+ if (!myrSleeve) throw new Error("Invalid move");
+ const dist = Math.abs(myrSleeve.x - x) + Math.abs(myrSleeve.y - y);
+ if (dist > 1) throw new Error("Invalid move");
+ return helpers.netscriptDelay(ctx, 100).then(function () {
+ myrSleeve.x = x;
+ myrSleeve.y = y;
+ return Promise.resolve();
+ });
+};
export function NetscriptMyrian(): InternalAPI {
return {
- ianUse: (ctx) => (_sleeveId, _x, _y) => {
- throw new Error("Unimplemented");
- },
- ianMove: (ctx) => async (_sleeveId, _x, _y) => {
- const id = helpers.number(ctx, "sleeveId", _sleeveId);
+ ianAct: (ctx) => (_action, _sleeveId, _x, _y) => {
+ const action = helpers.string(ctx, "action", _action);
const x = helpers.number(ctx, "x", _x);
const y = helpers.number(ctx, "y", _y);
- if (!player.sleeves[id]) throw new Error(`No sleeve with index ${id}`);
- const myrSleeve = myrian.sleeves.find((s) => s.index === id);
- if (!myrSleeve) return Promise.resolve();
- const dist = Math.abs(myrSleeve.x - x) + Math.abs(myrSleeve.y - y);
- if (dist > 1) return Promise.resolve();
- return helpers.netscriptDelay(ctx, 1000).then(function () {
- myrSleeve.x = x;
- myrSleeve.y = y;
- return Promise.resolve();
- });
+ const sleeveId = helpers.number(ctx, "sleeveId", _sleeveId);
+ switch (action) {
+ case MyrianActions.MOVE:
+ return move(ctx, sleeveId, x, y);
+ }
+ return Promise.reject("Invalid action");
+ },
+
+ ianWorldSize: (ctx) => () => {
+ return [myrian.world.length, myrian.world[0].length];
+ },
+
+ ianGetSleeve: (ctx) => (_sleeveId) => {
+ const sleeveId = helpers.number(ctx, "sleeveId", _sleeveId);
+ const sl = myrian.sleeves.find((s) => s.index === sleeveId);
+ if (!sl) {
+ return { inside: false, x: 0, y: 0 };
+ }
+ return { inside: true, x: sl.x, y: sl.y };
+ },
+
+ ianGetTile: (ctx) => (_x, _y) => {
+ const x = helpers.number(ctx, "x", _x);
+ const y = helpers.number(ctx, "y", _y);
+ return {
+ Content: myrian.world[y][x],
+ };
},
ianGetTask: (ctx) => (_sleeveId) => {
throw new Error("Unimplemented");
@@ -41,9 +69,6 @@ export function NetscriptMyrian(): InternalAPI {
ianLeave: (ctx) => (_sleeveId?) => {
throw new Error("Unimplemented");
},
- ianDeploy: (ctx) => (_sleeveId, _deploymentId, _x, _y) => {
- throw new Error("Unimplemented");
- },
ianApplyPowerup: (ctx) => (_sleeveId, _stat) => {
throw new Error("Unimplemented");
},
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index 85044aa56..71977669c 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -1,5 +1,7 @@
/** All netscript definitions */
+import { string } from "prop-types";
+
/** @public */
interface HP {
current: number;
@@ -2710,6 +2712,20 @@ export interface Hacknet {
getTrainingMult(): number;
}
+export interface MyrianTile {
+ Content: string;
+}
+
+export interface MyrianSleeve {
+ x: number;
+ y: number;
+ inside: boolean;
+}
+
+export declare enum MyrianActions {
+ MOVE = "MOVE",
+}
+
/**
* Myrian API
* @remarks
@@ -2719,28 +2735,18 @@ export interface Hacknet {
*/
export interface Myr {
/**
- * Interact with an object in The Myrian.
- * @remarks
+ * Take an action in The Myrian.
*
- * The effect is different depending on the object.
- * Interacting with an enemy will attack it.
- * With a resource node will mine it.
- * With a power up will collect it.
- * With a rock will try to break it.
- *
- * @returns Amount of milliseconds the operation will take.
+ * @returns A promise to be resolved when the action is over.
*/
- ianUse(sleeveId: number, x: number, y: number): number;
+ ianAct(action: MyrianActions, sleeveId: number, x: number, y: number): Promise;
/**
- * Move a sleeve in the Myrian.
- * @remarks
+ * Get the content of a tile.
*
- * The target tile must be 1 tile away from the sleeves current tile.
- *
- * @returns Amount of milliseconds the operation will take.
+ * @returns The content of the tile.
*/
- ianMove(sleeveId: number, x: number, y: number): Promise;
+ ianGetTile(x: number, y: number): MyrianTile;
/**
* Get that sleeves current task in the Myrian.
@@ -2759,6 +2765,18 @@ export interface Myr {
*/
ianCancelTask(sleeveId): boolean;
+ /**
+ * Get the size of the world.
+ * @returns [width, height] of the world.
+ */
+ ianWorldSize(): [number, number];
+
+ /**
+ * Get information about a sleeve and it's property related to The Myrian.
+ * @returns Information about a sleeve in The Myrian.
+ */
+ ianGetSleeve(sleeveId: number): MyrianSleeve;
+
/**
* Makes the player or a sleeve enter The Myrian.
* @remarks
@@ -2777,16 +2795,6 @@ export interface Myr {
*/
ianLeave(sleeveId?: number): boolean;
- /**
- * Deploy an entity in The Myrian.
- * @remarks
- *
- * Sleeves must be 1 tile away from the target tile and the player must have enough resources to build the entity.
- *
- * @returns The amount of milliseconds needed to complete the operation. or -1 if failed.
- */
- ianDeploy(sleeveId: number, deploymentId: number, x: number, y: number): number;
-
/**
* Apply a Myrian powerup to a sleeve.
* @remarks
@@ -6964,6 +6972,7 @@ export type NSEnums = {
LocationName: typeof LocationName;
ToastVariant: typeof ToastVariant;
UniversityClassType: typeof UniversityClassType;
+ MyrianActions: typeof MyrianActions;
};
/**
diff --git a/tsconfig.json b/tsconfig.json
index 28127e2fc..9db716a98 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -15,7 +15,7 @@
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
- "target": "es2022"
+ "target": "es2022"
},
"include": ["src/**/*", "electron/**/*", "node_modules/monaco-editor/monaco.d.ts"]
}