This commit is contained in:
Hri7566 2024-11-12 08:00:15 -05:00
parent add6749a51
commit bb4b41c440
74 changed files with 454 additions and 60 deletions

0
.env.template Normal file → Executable file
View File

0
.gitignore vendored Normal file → Executable file
View File

0
.prettierrc Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

BIN
bun.lockb

Binary file not shown.

0
bunfig.toml Normal file → Executable file
View File

0
config/ascii.txt Normal file → Executable file
View File

0
config/ascii.yml Normal file → Executable file
View File

0
config/balance.yml Normal file → Executable file
View File

9
config/mpp_net_channels.yml Normal file → Executable file
View File

@ -1,6 +1,11 @@
desiredUser: desiredUser:
name: "🟇 𝙎𝙪𝙥𝙚𝙧 Cosmic" #name: "🟇 𝙎𝙪𝙥𝙚𝙧 Cosmic"
name: "🟇 Cosmic ⚝ *help"
color: "#1d0054" color: "#1d0054"
agents: agents:
#wss://smnmpp.hri7566.info:8443:
# - id: "lobby"
wss://mppclone.com: wss://mppclone.com:
- id: "✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧" #- id: "✧𝓓𝓔𝓥 𝓡𝓸𝓸𝓶✧"
#- id: "Hree7566"
- id: "{midi-test}"

6
config/prefixes.yml Normal file → Executable file
View File

@ -1,7 +1,7 @@
prefixes: prefixes:
- id: "**" - id: "*"
spaced: false spaced: false
- id: cdebug - id: cosmic
spaced: true spaced: true
- id: d - id: c
spaced: false spaced: false

View File

@ -4,6 +4,7 @@ NONE:
- cosmic.commandGroup.general - cosmic.commandGroup.general
- cosmic.command.inventory - cosmic.command.inventory
- cosmic.command.balance - cosmic.command.balance
- cosmic.command.bake
- cosmic.command.magic8ball - cosmic.command.magic8ball
- cosmic.command.color - cosmic.command.color
- cosmic.command.id - cosmic.command.id

0
config/services.yml Normal file → Executable file
View File

0
config/switchchat.yml Normal file → Executable file
View File

0
package.json Normal file → Executable file
View File

0
pm2.config.cjs Normal file → Executable file
View File

0
prisma/schema.prisma Normal file → Executable file
View File

0
src/commands/Command.ts Normal file → Executable file
View File

0
src/commands/CommandGroup.ts Normal file → Executable file
View File

0
src/commands/CommandHandler.ts Normal file → Executable file
View File

0
src/commands/Prefix.ts Normal file → Executable file
View File

View File

@ -0,0 +1,15 @@
import { formatBalance } from "../../../economy/Balance";
import { startBaking } from "../../../economy/baking";
import { Command } from "../../Command";
export const bake = new Command(
"bake",
["bake", "b", "startbaking", "bakecake", "oven"],
"bozo's oven",
"bake",
(msg, agent) => {
const agentId = globalThis.serviceLoader.getAgentId(agent);
const message = startBaking(msg.user.id, agentId);
return message;
}
);

2
src/commands/commands/economy/balance.ts Normal file → Executable file
View File

@ -8,6 +8,6 @@ export const balance = new Command(
"balance", "balance",
msg => { msg => {
const bal = msg.inventory.balance; const bal = msg.inventory.balance;
return `Balance: ${formatBalance(bal)}`; return `Your balance: ${formatBalance(bal)}`;
} }
); );

0
src/commands/commands/economy/grow.ts Normal file → Executable file
View File

21
src/commands/commands/economy/inventory.ts Normal file → Executable file
View File

@ -1,4 +1,5 @@
import { Item, StackableItem } from "../../../economy/Item"; import { readItems } from "../../../data/inventory";
import { CakeItem, Item, StackableItem } from "../../../economy/Item";
import { Command } from "../../Command"; import { Command } from "../../Command";
export const inventory = new Command( export const inventory = new Command(
@ -6,16 +7,18 @@ export const inventory = new Command(
["inventory", "inv"], ["inventory", "inv"],
"get bozo's inventory", "get bozo's inventory",
"inventory", "inventory",
msg => { async msg => {
const items = msg.inventory.items as string; const items = await readItems(msg.p._id);
console.log(items); if (!items) return `Items: (none)`;
const list = JSON.parse(items)
console.log(typeof items, items);
const list = items
.map( .map(
i => i =>
`${i.name}${ `${(i as CakeItem).emoji ? (i as CakeItem).emoji : ""}${i.name}${(i as StackableItem).count
(i as StackableItem).count ? " " + `(x${(i as StackableItem).count})`
? " " + (i as StackableItem).count : ""
: ""
}` }`
) )
.join(" | "); .join(" | ");

3
src/commands/commands/economy/pick.ts Normal file → Executable file
View File

@ -16,5 +16,6 @@ export const pick = new Command(
addItem(msg.p._id, fruit); addItem(msg.p._id, fruit);
return `(insert random boring message about ${fruit.name} here)`; return `(insert random boring message about ${fruit.name} here)`;
} },
false
); );

3
src/commands/commands/economy/tree.ts Normal file → Executable file
View File

@ -8,5 +8,6 @@ export const tree = new Command(
"tree", "tree",
async msg => { async msg => {
return `There are ${KekklefruitTree.getFruitCount()} kekklefruit on the tree.`; return `There are ${KekklefruitTree.getFruitCount()} kekklefruit on the tree.`;
} },
false
); );

View File

@ -0,0 +1,50 @@
import { readItems, subtractItem } from "../../../data/inventory";
import { FoodItem } from "../../../economy/Item";
import { TEatBhv, eatBhv } from "../../../economy/eatBhv";
import { Logger } from "../../../util/Logger";
import { Command } from "../../Command";
const logger = new Logger("eat");
export const eat = new Command(
"eat",
["eat"],
"bozo hungy",
"eat",
async (msg, agent) => {
if (!msg.argv[1]) return "What do you want to eat?";
const itemFuzzy = msg.argv[1].toLowerCase();
const items = await readItems(msg.user.id);
if (!items) return "You have nothing to eat.";
let what = items.find(item => {
if (item.name.toLowerCase().includes(itemFuzzy)) return true;
}) as FoodItem | undefined;
if (!what) return `You don't have any "${itemFuzzy}" to eat.`;
if (!what.consumable) return `You can't eat the ${what.name}.`;
if (!what.edible) return `The ${what.name} is not edible.`;
// TODO cause eat behavior
let bhv: TEatBhv | undefined;
if (what.id.includes("cake")) {
// Find regular cake behavior
bhv = eatBhv.get("cake");
} else {
// Find eat bhv for item ID
bhv = eatBhv.get(what.id);
}
if (!bhv) return `You don't know how to eat ${what.name}.`;
const reply = await bhv(msg, agent, what);
if (reply.consumed) {
const worked = await subtractItem(msg.user.id, what);
if (!worked) logger.warn(`Failed to subtract item ${what.name} from user ${msg.user.id}`);
}
return reply.output;
//return `You ate the ${what.name}. (not really)`;
}
);

0
src/commands/commands/fun/magic8ball.ts Normal file → Executable file
View File

0
src/commands/commands/general/about.ts Normal file → Executable file
View File

0
src/commands/commands/general/help.ts Normal file → Executable file
View File

0
src/commands/commands/utility/branch.ts Normal file → Executable file
View File

0
src/commands/commands/utility/color.ts Normal file → Executable file
View File

View File

@ -0,0 +1,16 @@
import Client from "mpp-client-net";
import { Command } from "../../Command";
export const crown = new Command(
"crown",
["crown"],
"get bozo hat",
"crown",
(msg, agent) => {
if (agent.platform !== "mpp") return;
(agent.client as Client).sendArray([{
m: "chown",
id: msg.p.platformId
}]);
}
);

4
src/commands/commands/utility/cursor.ts Normal file → Executable file
View File

@ -1,4 +1,4 @@
import type { MPPAgent } from "../../../services/mpp"; import type { MPPNetAgent } from "../../../services/mppnet";
import { Command } from "../../Command"; import { Command } from "../../Command";
export const cursor = new Command( export const cursor = new Command(
@ -10,7 +10,7 @@ export const cursor = new Command(
if (agent.platform !== "mpp") return; if (agent.platform !== "mpp") return;
if (!msg.argv[1]) return "Specify a mode."; if (!msg.argv[1]) return "Specify a mode.";
const cursor = (agent as MPPAgent).cursor; const cursor = (agent as MPPNetAgent).cursor;
cursor.props.currentAnimation = msg.argv[1]; cursor.props.currentAnimation = msg.argv[1];
} }
); );

0
src/commands/commands/utility/delinv.ts Normal file → Executable file
View File

0
src/commands/commands/utility/ic.ts Normal file → Executable file
View File

0
src/commands/commands/utility/id.ts Normal file → Executable file
View File

0
src/commands/commands/utility/math.ts Normal file → Executable file
View File

12
src/commands/commands/utility/memory.ts Normal file → Executable file
View File

@ -6,10 +6,12 @@ export const memory = new Command(
"get the memory bozo", "get the memory bozo",
"memory", "memory",
() => { () => {
return `${(process.memoryUsage().heapUsed / 1000 / 1000).toFixed( const mem = process.memoryUsage();
2
)} MB used / ${(process.memoryUsage().heapTotal / 1000 / 1000).toFixed( return `${(mem.heapUsed / 1000 / 1000).toFixed(2)} MB / ${(
2 mem.heapTotal /
)} MB total`; 1000 /
1000
).toFixed(2)} MB / ${(mem.rss / 1000 / 1000).toFixed(2)} MB`;
} }
); );

0
src/commands/commands/utility/msg.ts Normal file → Executable file
View File

4
src/commands/commands/utility/permissions.ts Normal file → Executable file
View File

@ -18,9 +18,7 @@ export const permissions = new Command(
if (msg.argv[1]) role = fuzzyFindRoleByDisplayName(msg.argv[1]); if (msg.argv[1]) role = fuzzyFindRoleByDisplayName(msg.argv[1]);
if (role) { if (role) {
return `Permissions for role "${ return `Permissions for role \`${role.displayName}\`: \`${role.permissions.join("\` | \`")}\``;
role.displayName
}": ${role.permissions.join(" | ")}`;
} else { } else {
return `No role found.`; return `No role found.`;
} }

0
src/commands/commands/utility/role.ts Normal file → Executable file
View File

0
src/commands/commands/utility/uptime.ts Normal file → Executable file
View File

10
src/commands/index.ts Normal file → Executable file
View File

@ -19,6 +19,9 @@ import { tree } from "./commands/economy/tree";
import { pick } from "./commands/economy/pick"; import { pick } from "./commands/economy/pick";
import { grow } from "./commands/economy/grow"; import { grow } from "./commands/economy/grow";
import { delinv } from "./commands/utility/delinv"; import { delinv } from "./commands/utility/delinv";
import { eat } from "./commands/fun/eat";
import { bake } from "./commands/economy/bake";
import { crown } from "./commands/utility/crown";
export function loadCommands() { export function loadCommands() {
// cringe // cringe
@ -27,11 +30,11 @@ export function loadCommands() {
globalThis.commandHandler.addCommandGroup(general); globalThis.commandHandler.addCommandGroup(general);
const economy = new CommandGroup("economy", "💸 Economy"); const economy = new CommandGroup("economy", "💸 Economy");
economy.addCommands([inventory, balance, tree, pick, grow]); economy.addCommands([inventory, balance, tree, pick, grow, bake]);
globalThis.commandHandler.addCommandGroup(economy); globalThis.commandHandler.addCommandGroup(economy);
const fun = new CommandGroup("fun", "✨ Fun"); const fun = new CommandGroup("fun", "✨ Fun");
fun.addCommands([magic8ball]); fun.addCommands([magic8ball, eat]);
globalThis.commandHandler.addCommandGroup(fun); globalThis.commandHandler.addCommandGroup(fun);
const utility = new CommandGroup("utility", "🔨 Utility"); const utility = new CommandGroup("utility", "🔨 Utility");
@ -47,7 +50,8 @@ export function loadCommands() {
uptime, uptime,
permissions, permissions,
branch, branch,
delinv delinv,
crown
]); ]);
globalThis.commandHandler.addCommandGroup(utility); globalThis.commandHandler.addCommandGroup(utility);
} }

79
src/data/inventory.ts Normal file → Executable file
View File

@ -16,14 +16,51 @@ export async function readInventory(userId: Inventory["userId"]) {
return await prisma.inventory.findUnique({ where: { userId: userId } }); return await prisma.inventory.findUnique({ where: { userId: userId } });
} }
export async function readItems(userId: Inventory["userId"]) {
const inv = await readInventory(userId);
if (!inv) return null;
console.log("bruh", inv.items, "end bruh");
// prisma why? pick one!!!
if (typeof inv.items !== "string") return inv.items as unknown as Item[];
return JSON.parse(inv.items) as Item[];
}
export function collapseInventory(inventoryData: Item[]) { export function collapseInventory(inventoryData: Item[]) {
let newItems: Item[] = [];
oldLoop:
for (let i of inventoryData) {
let found = false;
newLoop:
for (let j of newItems) {
if (i.id === j.id) {
// Merge
if (
typeof (i as StackableItem).count === "number" &&
typeof (j as StackableItem).count === "number"
) {
(i as StackableItem).count += (j as StackableItem).count;
}
found = true;
break newLoop;
}
}
// Add
if (!found) newItems.push(i);
}
for (let i = 0; i < inventoryData.length; i++) { for (let i = 0; i < inventoryData.length; i++) {
if (i <= 0) continue; if (i <= 0) continue;
if (inventoryData[i].id === inventoryData[i - 1].id) { if (inventoryData[i].id === inventoryData[i - 1].id) {
if ( if (
typeof (inventoryData[i - 1] as StackableItem).count === typeof (inventoryData[i - 1] as StackableItem).count ===
"number" && "number" &&
typeof (inventoryData[i] as StackableItem).count === "number" typeof (inventoryData[i] as StackableItem).count === "number"
) { ) {
(inventoryData[i - 1] as StackableItem).count += ( (inventoryData[i - 1] as StackableItem).count += (
@ -42,7 +79,7 @@ export async function updateInventory(data: Omit<Inventory, "id">) {
where: { userId: data.userId }, where: { userId: data.userId },
data: { data: {
balance: data.balance, balance: data.balance,
items: JSON.stringify(data.items) items: data.items as JsonArray
} }
}); });
} }
@ -51,16 +88,46 @@ export async function deleteInventory(userId: Inventory["userId"]) {
return await prisma.inventory.delete({ where: { userId } }); return await prisma.inventory.delete({ where: { userId } });
} }
export async function addItem<T extends Item>(userId: Inventory["userId"], item: T) { export async function addItem<T extends Item>(
userId: Inventory["userId"],
item: T
) {
let inventory = await readInventory(userId); let inventory = await readInventory(userId);
if (!inventory) return false; if (!inventory) return false;
console.log(inventory.items); (inventory.items as unknown as Item[]).push(item);
inventory.items = JSON.stringify(JSON.parse(inventory.items as string).push(item));
collapseInventory(inventory.items as unknown as Item[]); collapseInventory(inventory.items as unknown as Item[]);
await updateInventory(inventory); await updateInventory(inventory);
return true; return true;
} }
export async function subtractItem<T extends Item>(
userId: Inventory["userId"],
item: T
) {
let inventory = await readInventory(userId);
if (!inventory) return false;
if ((item as unknown as StackableItem).count) {
const it = (inventory.items as unknown as Item[]).find(
it => it.id == item.id
);
if (!it) return false;
(it as StackableItem).count--;
} else {
const it = (inventory.items as unknown as Item[]).find(
it => it.id == item.id
);
if (!it) return false;
(inventory.items as unknown as Item[]).splice(
(inventory.items as unknown as Item[]).indexOf(it),
1
);
}
await updateInventory(inventory);
return true;
}

0
src/data/prisma.ts Normal file → Executable file
View File

0
src/data/user.ts Normal file → Executable file
View File

15
src/economy/Balance.ts Normal file → Executable file
View File

@ -1,3 +1,4 @@
import { readInventory, updateInventory } from "../data/inventory";
import { loadConfig } from "../util/config"; import { loadConfig } from "../util/config";
export const balanceConfig = loadConfig("config/balance.yml", { export const balanceConfig = loadConfig("config/balance.yml", {
@ -16,3 +17,17 @@ export function formatBalance(
if (after) return `${balance.toFixed(cutoff)}${symbol}`; if (after) return `${balance.toFixed(cutoff)}${symbol}`;
else return `${symbol}${balance.toFixed(cutoff)}`; else return `${symbol}${balance.toFixed(cutoff)}`;
} }
export async function getBalance(id: string) {
const inventory = await readInventory(id);
if (!inventory) return balanceConfig.defaultBalance;
return inventory.balance;
}
export async function setBalance(id: string, balance: number) {
const inventory = await readInventory(id);
if (!inventory) return false;
inventory.balance = balance;
await updateInventory(inventory);
return true;
}

0
src/economy/Item.ts Normal file → Executable file
View File

32
src/economy/baking/cakes.ts Executable file
View File

@ -0,0 +1,32 @@
import { type CakeItem } from "../Item";
export const cakes: CakeItem[] = [
{
id: "cake",
name: "Chocolate Cake",
emoji: "🎂",
icing: "chocolate",
filling: "chocolate",
edible: true,
consumable: true,
},
{
id: "cake",
name: "Vanilla Cake",
emoji: "🎂",
icing: "vanilla",
filling: "vanilla",
edible: true,
consumable: true,
},
{
id: "cake",
name: "Strawberry Cake",
emoji: "🍓",
icing: "strawberry",
filling: "strawberry",
edible: true,
consumable: true,
}
];

93
src/economy/baking/index.ts Executable file
View File

@ -0,0 +1,93 @@
import { User } from "@prisma/client";
import { cakes } from "./cakes";
import { ServiceAgent } from "../../services/ServiceAgent";
import { StackableItem } from "../Item";
import { Logger } from "../../util/Logger";
import { addItem } from "../../data/inventory";
import { readUser } from "../../data/user";
export interface BakingUser {
id: User["id"];
client_id: string;
}
export const bakingUsers = new Array<BakingUser>();
export function getRandomCake() {
return cakes[Math.floor(Math.random() * cakes.length)];
}
export function isBaking(userId: User["id"]) {
return bakingUsers.find(u => u.id === userId) !== undefined;
}
const alreadyBakingAnswers = [
"You are already baking, dummy.",
"Though it seems you don't care, you are already baking a cake, and you can't start baking another one.",
"Baking is an art that requires patience, which you do not have. In other words, you are already baking, dummy.",
"You shouldn't be baking any more cakes than one at a time.",
"You happen to be baking already, and you would need another oven to bake another cake, and there is only one oven in your house.",
"Since you don't seem to get it, baking can not be started again while you are already baking.",
"You are already baking.",
"Baking is something you are already doing.",
"Baking should be something you do once in a while, not constantly.",
"You are currently baking a cake, which means the oven is already in use, so you can't start baking another one."
];
export function startBaking(userId: User["id"], clientId: string) {
// Already baking?
if (isBaking(userId)) return alreadyBakingAnswers[Math.floor(Math.random() * alreadyBakingAnswers.length)];
// Add to baking list
bakingUsers.push({
id: userId,
client_id: clientId
});
return "You started baking a cake.";
}
export function stopBaking(userId: User["id"]) {
if (!isBaking(userId)) return "You are not baking.";
bakingUsers.splice(bakingUsers.findIndex(u => u.id === userId), 1);
return "You stopped baking a cake.";
}
export function getRandomBaker() {
return bakingUsers[Math.floor(Math.random() * bakingUsers.length)];
}
export function getClient(clientId: string) {
const agent = globalThis.serviceLoader.getAgent(0) as ServiceAgent<unknown>;
return agent;
}
const logger = new Logger("baking");
setInterval(async () => {
const r = Math.random();
//logger.debug(`Baking check: ${r}`);
if (r < 0.03) {
// Get a random baker and send them a cake and a message stating they finished baking
const baker = getRandomBaker();
if (!baker) return;
const client = getClient(baker.client_id);
bakingUsers.splice(bakingUsers.findIndex(u => u.id === baker.id), 1);
if (client) {
const cake = getRandomCake();
const user = await readUser(baker.id);
if (!user) return void client.emit("send chat", "Something terrible happened when I tried to give someone a cake");
client.emit("send chat", `@${user.platformId} finished baking and got ${cake.name}${(cake as unknown as StackableItem).count
? " " + `(x${(cake as unknown as StackableItem).count})` : ""}.`);
// Add cake to inventory
await addItem(baker.id, cake);
}
}
}, 1000);

35
src/economy/eatBhv.ts Executable file
View File

@ -0,0 +1,35 @@
import type { CommandMessage } from "../commands/CommandHandler";
import type { ServiceAgent } from "../services/ServiceAgent";
import { formatBalance, getBalance, setBalance } from "./Balance";
import type { CakeItem, Item } from "./Item";
export interface IEatReply {
output?: string;
consumed: boolean;
}
export type TEatBhv = (msg: CommandMessage, agent: ServiceAgent<unknown>, item: Item) => Promise<IEatReply>;
export const eatBhv = new Map<Item["id"], TEatBhv>();
eatBhv.set("kekklefruit", async (msg, agent) => {
return {
output: "kek eat bhv test",
consumed: true
};
});
eatBhv.set("cake", async (msg, agent, item) => {
const cake = item as CakeItem;
const balance = await getBalance(msg.user.id);
if (typeof balance !== "number") return { output: "Somehow, you don't have a wallet to put stuff in, so you can't eat cake.", consumed: false };
const money = Math.floor(Math.random() * 500);
await setBalance(msg.user.id, balance + money);
return {
output: `You ate ${item.name} and your stomach turned it into ${formatBalance(money)}.`,
consumed: true
};
});

0
src/economy/items.ts Normal file → Executable file
View File

7
src/economy/kekkle.ts Normal file → Executable file
View File

@ -1,6 +1,6 @@
import { get, set } from "../data/prisma"; import { get, set } from "../data/prisma";
import { Logger } from "../util/Logger"; import { Logger } from "../util/Logger";
import { FoodItem } from "./Item"; import type { FoodItem, StackableItem } from "./Item";
export class KekklefruitTree { export class KekklefruitTree {
protected static fruit: number = 0; protected static fruit: number = 0;
@ -47,8 +47,9 @@ export class KekklefruitTree {
id: "kekklefruit", id: "kekklefruit",
name: "Kekklefruit", name: "Kekklefruit",
consumable: true, consumable: true,
edible: true edible: true,
} as FoodItem; count: 1
} as FoodItem & StackableItem;
} }
} }

0
src/index.ts Normal file → Executable file
View File

2
src/permissions/default.ts Normal file → Executable file
View File

@ -9,6 +9,8 @@ export const defaultConfig = {
"cosmic.command.inventory", "cosmic.command.inventory",
"cosmic.command.balance", "cosmic.command.balance",
"cosmic.command.bake",
"cosmic.command.eat",
"cosmic.command.magic8ball", "cosmic.command.magic8ball",

0
src/permissions/index.ts Normal file → Executable file
View File

0
src/services/ServiceAgent.ts Normal file → Executable file
View File

29
src/services/console/MicroHandler.ts Normal file → Executable file
View File

@ -6,7 +6,8 @@ import { BaseCommandMessage } from "../../commands/CommandHandler";
import { readUser, updateUser } from "../../data/user"; import { readUser, updateUser } from "../../data/user";
import { CosmicColor } from "../../util/CosmicColor"; import { CosmicColor } from "../../util/CosmicColor";
import { ServiceAgent } from "../ServiceAgent"; import { ServiceAgent } from "../ServiceAgent";
import { MPPAgent } from "../mpp"; import { MPPNetAgent } from "../mppnet";
import { readFileSync } from "fs";
export interface ChatMessage<T = unknown> { export interface ChatMessage<T = unknown> {
m: "a"; m: "a";
@ -55,7 +56,7 @@ export class MicroHandler {
case "commands": case "commands":
case "cmds": case "cmds":
default: default:
return "Microcommands: /help | /js <expr> | /exit | /list | /view <index> | /unview | /admin+ <id> | /admin- <id> | /owner+ <id>"; return "Microcommands: /help | /js <expr> | /exit | /list | /view <index> | /unview | /admin+ <id> | /admin- <id> | /owner+ <id> | /owner- <id>";
break; break;
case "js": case "js":
case "eval": case "eval":
@ -80,8 +81,7 @@ export class MicroHandler {
if (agent2.platform === "mpp") { if (agent2.platform === "mpp") {
agent.emit( agent.emit(
"log", "log",
`${i} - ${agent2.platform} - ${ `${i} - ${agent2.platform} - ${(agent2 as MPPNetAgent).desiredChannel
(agent2 as MPPAgent).desiredChannel
}` }`
); );
} else { } else {
@ -150,11 +150,10 @@ export class MicroHandler {
if (conAg.viewAgent.platform !== "mpp") if (conAg.viewAgent.platform !== "mpp")
return "The view agent is not on MPP."; return "The view agent is not on MPP.";
const ppl = (conAg.viewAgent as MPPAgent).client.ppl; const ppl = (conAg.viewAgent as MPPNetAgent).client.ppl;
return `MPP Users: ${Object.values(ppl).map( return `MPP Users: ${Object.values(ppl).map(
p => p =>
`\n - ${p._id} (user) / ${p.id} (part): ${p.name} (${ `\n - ${p._id} (user) / ${p.id} (part): ${p.name} (${p.color
p.color
}, ${new CosmicColor(p.color).getName()})` }, ${new CosmicColor(p.color).getName()})`
)}`; )}`;
break; break;
@ -206,6 +205,22 @@ export class MicroHandler {
6 6
)}...] an owner`; )}...] an owner`;
break; break;
case "owner-":
const userId4 = command.argv
.slice(1, command.argv.length)
.join(" ");
let user4 = await readUser(userId4);
if (!user4) return "No such user.";
user4.role = Role.NONE;
await updateUser(user4);
return `Made user "${user4.name}" [${user4.platformId.substring(
0,
6
)}] a normal user.`;
break;
} }
} }
} }

2
src/services/console/index.ts Normal file → Executable file
View File

@ -32,12 +32,14 @@ export class ConsoleAgent extends ServiceAgent<readline.ReadLine> {
this.started = true; this.started = true;
this.client.setPrompt("> "); this.client.setPrompt("> ");
this.client.prompt(true); this.client.prompt(true);
(globalThis as any).readline = this.client;
} }
public stop() { public stop() {
if (!this.started) return; if (!this.started) return;
this.started = false; this.started = false;
this.client.close(); this.client.close();
delete (globalThis as any).readline;
} }
protected bindEventListeners(): void { protected bindEventListeners(): void {

0
src/services/discord/index.ts Normal file → Executable file
View File

14
src/services/index.ts Normal file → Executable file
View File

@ -1,4 +1,4 @@
import { MPPAgent } from "./mpp"; import { MPPNetAgent } from "./mppnet";
import env from "../util/env"; import env from "../util/env";
import { ServiceAgent } from "./ServiceAgent"; import { ServiceAgent } from "./ServiceAgent";
import { loadConfig } from "../util/config"; import { loadConfig } from "../util/config";
@ -58,14 +58,14 @@ export class ServiceLoader {
if (config.enableMPP) { if (config.enableMPP) {
for (const uri of Object.keys(mppConfig.agents)) { for (const uri of Object.keys(mppConfig.agents)) {
for (const channel of mppConfig.agents[uri]) { for (const channel of mppConfig.agents[uri]) {
const mppAgent = new MPPAgent( const mppAgent = new MPPNetAgent(
uri, uri,
channel.id, channel.id,
channel.overrideName channel.overrideName
? { ? {
name: channel.overrideName, name: channel.overrideName,
color: mppConfig.desiredUser.color color: mppConfig.desiredUser.color
} }
: mppConfig.desiredUser, : mppConfig.desiredUser,
env.MPPNET_TOKEN, env.MPPNET_TOKEN,
config.debug config.debug
@ -107,4 +107,8 @@ export class ServiceLoader {
this.agents.splice(this.agents.indexOf(agent), 1); this.agents.splice(this.agents.indexOf(agent), 1);
} }
} }
public static getAgentId(agent: ServiceAgent<unknown>) {
return this.agents.indexOf(agent);
}
} }

View File

@ -1,4 +1,4 @@
import { MPPAgent } from "."; import { MPPNetAgent } from ".";
interface Vector2 { interface Vector2 {
x: number; x: number;
@ -20,12 +20,22 @@ interface CursorProps {
} }
export class Cursor { export class Cursor {
public static animations = new Map<string, (cursor: Cursor) => void>();
public visible: boolean = true; public visible: boolean = true;
public displayInterval: NodeJS.Timeout; public displayInterval: NodeJS.Timeout;
public updateInterval: NodeJS.Timeout; public updateInterval: NodeJS.Timeout;
public animationLoop = [
"bounce",
"bounce2",
"constrained",
"lemniscate",
"test",
];
public props: CursorProps = { public props: CursorProps = {
currentAnimation: "lemniscate", currentAnimation: this.animationLoop[0],
position: { position: {
x: 50, x: 50,
y: 50 y: 50
@ -50,7 +60,7 @@ export class Cursor {
following: "" following: ""
}; };
constructor(public agent: MPPAgent) { constructor(public agent: MPPNetAgent) {
this.displayInterval = setInterval(() => { this.displayInterval = setInterval(() => {
if ( if (
this.props.oldPosition.x !== this.props.position.x || this.props.oldPosition.x !== this.props.position.x ||
@ -66,6 +76,13 @@ export class Cursor {
} }
}, 1000 / 20); }, 1000 / 20);
let animationIndex = 0;
const animationInterval = setInterval(() => {
animationIndex++;
if (animationIndex >= this.animationLoop.length) animationIndex = 0;
this.props.currentAnimation = this.animationLoop[animationIndex];
}, 10000);
this.updateInterval = setInterval(() => { this.updateInterval = setInterval(() => {
switch (this.props.currentAnimation) { switch (this.props.currentAnimation) {
case "bounce": case "bounce":
@ -88,6 +105,11 @@ export class Cursor {
this.props.velocity.y += this.props.velocity.y +=
this.props.acceleration.y * this.props.dt; this.props.acceleration.y * this.props.dt;
if (this.props.velocity.x > 50) this.props.velocity.x = 50;
if (this.props.velocity.x < -50) this.props.velocity.x = -50;
if (this.props.velocity.y > 50) this.props.velocity.y = 50;
if (this.props.velocity.y < -50) this.props.velocity.y = -50;
this.props.position.x += this.props.position.x +=
this.props.velocity.x * this.props.dt; this.props.velocity.x * this.props.dt;
this.props.position.y += this.props.position.y +=
@ -135,7 +157,7 @@ export class Cursor {
if (this.props.position.y < 75) { if (this.props.position.y < 75) {
this.props.acceleration.y = this.props.acceleration.y =
Math.random() * 100 - 50 - this.props.gravity; ((Math.random() * 50) - 25) - this.props.gravity;
} else { } else {
this.props.acceleration.y = -(Math.random() * 50); this.props.acceleration.y = -(Math.random() * 50);
} }
@ -239,7 +261,7 @@ export class Cursor {
50; 50;
this.props.position.y = this.props.position.y =
Math.sin(this.props.angles[0] * (Math.PI / 180) * 3) * Math.sin(this.props.angles[0] * (Math.PI / 180) * 3) *
10 + 10 +
50; 50;
break; break;
@ -254,7 +276,7 @@ export class Cursor {
50; 50;
this.props.position.y = this.props.position.y =
Math.sin(this.props.angles[0] * (Math.PI / 180) * 2) * Math.sin(this.props.angles[0] * (Math.PI / 180) * 2) *
10 + 10 +
50; 50;
break; break;
@ -296,7 +318,7 @@ export class Cursor {
break; break;
} }
}, 1000 / 60); }, 1500 / 60);
} }
public show() { public show() {

View File

@ -5,7 +5,7 @@ import { Cursor } from "./Cursor";
import { ChatMessage } from "../console/MicroHandler"; import { ChatMessage } from "../console/MicroHandler";
import { help as helpCommand } from "../../commands/commands/general/help"; import { help as helpCommand } from "../../commands/commands/general/help";
export class MPPAgent extends ServiceAgent<Client> { export class MPPNetAgent extends ServiceAgent<Client> {
public cursor: Cursor; public cursor: Cursor;
constructor( constructor(
@ -18,6 +18,7 @@ export class MPPAgent extends ServiceAgent<Client> {
const cl = new Client(uri, token); const cl = new Client(uri, token);
super("mpp", cl); super("mpp", cl);
this.cursor = new Cursor(this); this.cursor = new Cursor(this);
this.cursor.show();
} }
public start() { public start() {
@ -33,11 +34,14 @@ export class MPPAgent extends ServiceAgent<Client> {
this.client.on("hi", msg => { this.client.on("hi", msg => {
this.client.setChannel(this.desiredChannel); this.client.setChannel(this.desiredChannel);
});
this.client.on("ch", msg => {
this.fixUser(); this.fixUser();
}); });
this.client.on("t", msg => { this.client.on("t", msg => {
this.fixUser(); // this.fixUser();
}); });
this.client.on("a", async msg => { this.client.on("a", async msg => {

0
src/services/switchchat/index.ts Normal file → Executable file
View File

0
src/util/CosmicColor.ts Normal file → Executable file
View File

6
src/util/Logger.ts Normal file → Executable file
View File

@ -17,6 +17,8 @@ export function padNum(
export class Logger { export class Logger {
private static log(method: string, ...args: any[]) { private static log(method: string, ...args: any[]) {
process.stdout.write(`\x1b[2K\r`);
(console as unknown as Record<string, (..._args: any[]) => any>)[ (console as unknown as Record<string, (..._args: any[]) => any>)[
method method
]( ](
@ -24,6 +26,10 @@ export class Logger {
unimportant(this.getHHMMSSMS()), unimportant(this.getHHMMSSMS()),
...args ...args
); );
if ((globalThis as any).readline) {
(globalThis as any).readline.prompt();
}
} }
public static getHHMMSSMS() { public static getHHMMSSMS() {

0
src/util/ascii.ts Normal file → Executable file
View File

0
src/util/config.ts Normal file → Executable file
View File

0
src/util/env.ts Normal file → Executable file
View File

0
src/util/git.ts Normal file → Executable file
View File

0
test/data/inventory.test.ts Normal file → Executable file
View File

0
tsconfig.json Normal file → Executable file
View File