Add kekklefruit (no item behavior yet)

This commit is contained in:
Hri7566 2024-03-05 14:27:46 -05:00
parent 72841dbe17
commit af89379aa2
16 changed files with 583 additions and 3 deletions

9
config/permissions.yml Normal file
View File

@ -0,0 +1,9 @@
- id: default
permissions:
- command.general.*
- command.fishing.*
- command.inventory.*
- command.util.*
- id: owner
permissions:
- "*"

View File

@ -46,3 +46,8 @@ model KeyValueStore {
id Int @id @default(0)
json Json @default("{}")
}
model UserPermission {
userId String @id @unique
groupId String
}

View File

@ -0,0 +1,21 @@
import { getAllTokens } from "@server/data/token";
import { ReadlineCommand } from "../ReadlineCommand";
import { setUserGroup } from "@server/data/permissions";
export const setgroup = new ReadlineCommand(
"setgroup",
["setgroup"],
"Set a user's permission group",
"setgroup <user ID> <group ID>",
async line => {
const args = line.split(" ");
const userID = args[1];
const groupID = args[2];
if (!userID) return "Please provide a user ID.";
if (!groupID) return "Please provide a group ID.";
await setUserGroup(userID, groupID);
return `User's group is now ${groupID}.`;
}
);

View File

@ -0,0 +1,318 @@
import Command from "@server/commands/Command";
import { getInventory, updateInventory } from "@server/data/inventory";
import { genFruitAndRemove, getFruitCount, hasFruit } from "@server/fish/tree";
import { addItem } from "@server/items";
export const pick = new Command(
"pick",
["pick", "pock"],
"Pick a fruit off the Kekklefruit Tree.",
"pick",
"command.fishing.pick",
async ({ id, command, args, prefix, part, user, isDM }) => {
const inventory = await getInventory(user.inventoryId);
if (!inventory) return;
if (!(await hasFruit()))
return crazy[Math.floor(Math.random() * crazy.length)];
const fruit = await genFruitAndRemove();
addItem(inventory.items as unknown as IObject[], fruit);
await updateInventory(inventory);
return `Our friend ${part.name} picked 1 fruit from the kekklefruit tree and placed it into his/her inventory.`;
}
);
const crazy = [
"The tree is devoid of fruit.",
"The tree is without fruit.",
"The tree is barren.",
"The tree is missing all its fruit.",
"The tree is not with fruit.",
"The tree is without fruit.",
"The tree is not showing any fruit.",
"The tree is not bearing fruit.",
"The tree has not borne fruit.",
"The tree is not showing fruit.",
"The tree is not carrying fruit.",
"The tree is not holding fruit.",
"The tree is at 0 fruit.",
"The tree has no fruit.",
"The tree doesn't have any fruit to give.",
"The tree doesn't have any fruit to take.",
"The tree doesn't have any fruit left to plunder...",
"The tree has not grown any new fruit.",
"The tree can't give any more fruit right now.",
"The fruit have all been taken.",
"The fruit have all been picked.",
"You don't see any fruit on the tree.",
"Your hand is without fruit. After reaching to pick one",
"No fruit because there aren't any on the tree.",
"No kekklefruit was upon the tree.",
"The tree has long slender limbs, barren of fruit.",
"The tree's limbs are not currently baring any fruit.",
"This tree doesn't have fruit.",
"Fruit are not a thing currently on the tree.",
"Could not get fruit.",
"Try again, please.",
"(no fruit picked)",
"It just doesn't have any fruit.",
"There aren't any fruit.",
"Can't get fruit, there's no fruit.",
"The tree's not growing!!!!!!!",
"Give the tree some time to grow fruit.",
"The tree will grow fruit given time.",
"The tree will have fruit again.",
"The tree's just sitting there. Fruitless.",
"It'll grow fruit, give it a second.",
"Keep trying, but wait until the tree has fruit.",
"Wait until the tree has fruit.",
"Pick again in a bit because the tree doesn't have any fruit right now.",
"There aren't any fruit on the kekklefruit tree",
"You pore over each branch meticulously looking for fruit, but are still coming back empty.",
"You scour every branch of the tree for fruit, but still came back empty-handed.",
"You try caressing the tree's body. It didn't work.",
"You try tugging on one of the branches. It doesn't work.",
"You started picking the fruit when you heard a sound or something that distracted you and made you forget what you were doing. Then, you remember: you tried to pick a fruit. You take a deep breath and decide to try again",
"You could have sworn you were wrapping your hand around a sweet kekklefruit, but it seemingly disappeared from reality right as you grasped it??",
"No fruit.",
"Trying again, there were no fruit to pick.",
"There were no fruit to pick.",
"There was no fruit for you to pick.",
"There isn't anything that looks like a fruit growing on the tree, yet...",
"The fruit just isn't edible yet.",
"It's not ready, keep trying though.",
"It's not ready...!",
"It's not done.",
"Wait, give it time to grow fruit.",
"Just wait for the fruit to grow.",
"Wait for the fruit to grow. But don't wait until someone else grabs it first.",
"You have to give the precious kekklefruits time to grow.",
"Hold on, they're growing.",
"Hold on.",
"Watch the kekklefruit to make sure they have grown before picking them from the tree.",
"Don't pick the kekklefruit until they're grown.",
"The kekklefruit are still maturing.",
"There isn't a pickable kekklefruit.",
"You don't see any.",
"I don't see any.",
"It's like every time the tree grows fruit somebody is stealing it.",
"Every time the tree grows fruit, somebody picks it.",
"There's no fruit, so wait.",
"Keep trying to get fruit.",
"The fruit will be fine... when it grows.",
"The fruit will do fine. Then, pick it.",
"The fruit looks like you could almost pick it!",
"Picking is not available right now.",
"Please try again later.",
"No fruit.",
"Look here. Look there. No fruit anywhere.",
"The fruit just isn't there to pick.",
"You can't pick the fruit because it's not ready to be picked.",
"Don't pick the fruit until it finishes growing into a pickable fruit.",
"Let the fruit grow, first.",
"The tree is out of fruit.",
"The tree's fruit count remains 0.",
"Tree fruit unavailable.",
"You try, but there's no fruit.",
"The tree ran out of fruit.",
"No pickable fruit.",
"People took the tree's fruit.",
"The tree was picked over entirely.",
"The tree just didn't have any more fruit to give.",
"The tree asked you to try again, please.",
"The tree branches looked sinister with no fruit on them at all.",
"Without its fruit, the tree looks kinda scary.",
"The tree doesn't have fruit anymore.",
"The tree doesn't have fruit anymore. It looks weird that way.",
"The tree's long slender branches reached high into the sky, looking nude without their fruit.",
"Robbed of its precious fruit, the tree loomed despondently.",
'The tree doesn\'t "have" fruit.',
"After much consideration, you decide to maybe sayer a prayer for the tree.",
"The action you have taken upon the tree was fruitless.",
"No fruit, just now, not on the tree, here.",
"You didn't get any fruit.",
"The tree's fruit supply is depleted.",
"This tree has a strange animosity.",
"They took it all.",
"There's no more fruit.",
"Don't have any fruit.",
"You just have to wait for kekklefruit.",
"Wait for fruit.",
"Wait for fruit growth.",
"Wait for the fruit growth.",
"Wait for fruit to grow on the tree.",
"Those tree fruit are just hard to come by right now.",
"I haven't seen a fruit",
"It didn't produce fruit yet.",
"You're still waiting for it to produce fruit.",
"You're still waiting for fruit to grow.",
"The tree is bone dry! Sans fruit!",
"God, you'd do anything for a fruit. But not yet.",
"Just be patient.",
"Be patient.",
"Wait patiently for fruit.",
"Your fruit will grow, just wait.",
"Waiting for your fruit to grow.",
"Pick the next fruit that grows.",
"Pick a fruit after it grows.",
"Get a fruit from the tree after they grow.",
"Pick again after the tree has had time to grow fruit.",
"Not yet, it's hasn't grown fruit yet.",
"Wait a second, no fruit yet.",
"You can has fruit after it grows.",
"Try again repeatedly to see if you get a fruit or not.",
"Try again, it grows fruit periodically.",
"Wait",
"No fruit just yet",
"No fruit yet",
"Noooot yet",
"Just a little longer.",
"Wait between each pick for fruit to grow.",
"After a wait, fruit will grow on the tree.",
"The tree's gonna grow plenty of fruit, just give it time.",
"Without its fruit, this tree is looking slightly eerie.",
"What a funny-looking tree without its fruit!",
"You notice the way the tree looks without fruit.",
"You notice the tree looks kinda odd with no fruit like that.",
"You don't like looking at the tree when it doesn't have fruit.",
"You express your desire for the tree to grow fruit.",
"You're waiting for the fruit to grow so you can pick it.",
"Ugh, no fruit..",
"Keep trying to get fruit.",
"The fruit gave under the forces... I guess it wasn't ready yet.",
"The fruit's branches hadn't decided to tree yet.",
"The fruit wasn't available.",
"It's almost time for a fruit to be pickable.",
"Should be a fruit pickable soon.",
"It'll grow fruit for you to pick in a minute.",
"It'll grow in a minute.",
"It'll grow.",
"It'll grow fruit.",
"The fruit will grow on the tree's BRANCHES.",
"You don't spy any fruit on the tree's branches.",
"The tree's branches can be seen in detail without the fruit interrupting our view.",
"You make sure, and there's no fruit on the tree.",
"You search the tree for fruit, and are 100% sure there are none.",
"You're 100% sure there aren't any pickable fruit yet.",
"You try, but don't find any fruit.",
"You look, but don't find any fruit.",
"Can't see any FRUIT.",
"Couldn't /pick",
"It's just that there aren't any fruit on the tree.",
"These things take time.",
"These things can sometimes take time.",
"You can't rush these things.",
"You practice picking the fruit (there aren't any on the tree)",
"It doesn't look like there are any fruit on the tree.",
"0 kinds of fruit are growing on this tree",
"You feel good about the possibility of fruit growing on the tree eventually.",
"You whisper for the tree to grow nice fruits.",
"This is exciting! It'll grow fruit that you can eat.",
"Alas, the tree wasn't currently displaying any fruit.",
"Any fruit on the tree? No...",
"No fruit? Okay...",
"A quick scan shows no fruits on the tree that are ready for picking.",
"You check and don't see any fruit.",
"You give the tree a once-over to see if any fruit area ready. Not yet, but you are resolute...",
"You check on the tree. No fruit, back to whatever it was you were doing.",
"If this tree doesn't grow fruit soon you might start to get crazy.",
"Actually, what if the tree doesn't grow any more fruit?",
"What if the fruit never grows again?",
"Ok, there's no fruit.",
"You consider again what might happen if the fruit stopped growing.",
"There is no fruit, so you just ponder about the tree.",
"There's no fruit, so you just consider it for a moment.",
"There's no fruit, so you think about the tree situation for another moment and then move on.",
"There are no fruits, so you decided to talk about something else.",
"Missed!",
"Didn't chance upon a fruit.",
"Didn't find the fruit.",
"No fruit found.",
"It's gonna be good fruit.",
"The fruit from the tree will never change.",
"The fruit from this tree will always grow, as long as the tree stands, at a pretty steady rate.",
"You survey the tree for fruit, coming back empty-handed.",
"It's not like the tree is on strike from producing fruit.",
"The valuable fruit are not present.",
"The revered fruit have been lost.",
"You study the tree's fruitless branches.",
"Good view of the branches with no fruit on them.",
"Patiently and rapidly retry your command.",
"You use a phone app to make sure the tree doesn't have any pickable fruit.",
"You scan each fruit, finding no candidates for picking.",
"The fruit of the tree are too young and supple to pick.",
"You can't reach that one fruit up there.",
"Oh, there's one. But you can't reach it.",
"You trying to pick fruit that isn't there.",
"Where do you see fruit?",
"Looks like the fruit aren't out today.",
"You wonder what the fruit are doing.",
"You wonder when the tree will bear fruit.",
"You wonder when a fruit will be ready.",
"You wonder if a fruit will grow.",
"You think about how many fruits this tree must have produced with nobody even counting it or anything.",
"You wonder how many fruit this tree has grown in its lifetime.",
"It's not that time, yet.",
"It's not time.",
"Not... yet.",
"The auto-analysis didn't show any completed fruit.",
"The fruit aren't complete.",
"Waiting for fruit growth completion.",
"Please wait for the fruit to be ready.",
"Don't rush it.",
"Slow down, there aren't any fruit to pick yet.",
"You check the fruit indicator under your favorite kekklefruit tree. It reads: 0.",
"Nope, don't see any.",
"Is something taking all the fruit?",
"I guess somebody else picked the fruit first.",
"Somebody else got to it first.",
"This",
"If you focus, the fruit grows faster.",
"You meditate to make the fruit grow faster.",
"What you are doing doesn't make the fruit grow.",
"Don't be too greedy.",
"Fruit pick intercepted.",
"Intercepted, try again.",
"Denied. Try again for success.",
"False success message, no fruit actually picked",
"I swear it'll grow fruit eventually lol",
"You don't know how long it'll take before fruit grows on the tree.",
"You don't know how long before the fruit will grow on the tree.",
"Nobody knows how long it takes for fruit to grow on the tree.",
"The tree says 'no'",
"No fruit, but that's okay.",
"Don't worry about it.",
"No fruit but it's quite alright.",
"No fruit right now.",
"Not a good time to pick fruit.",
"It's probably not a good idea",
"Ha ha don't worry!",
"Lol don't sweat it",
"It's alright! It's just a temporary lack of fruit!",
"Seems like famine again",
"What's wrong with the tree?",
"Is the tree okay?",
"What's this tree for...?",
"Is something wrong with the tree?",
"Try singing the tree a song.",
"The tree doesn't look like it's up to it righ tnow.",
"The tree doesn't look so good.",
"The tree doesn't feel so good.",
"The tree doesn't look like it feels so good.",
"The tree isn't ready right now!",
"Back off and give the tree some time!!",
"Hands off until the tree grows fruit.",
"Patience.",
"Impatience.",
"no",
"Fruit not available",
"There are no fruits there.",
"No fruits upon the tree!",
"That didn't work.",
"Nope, no fruit.",
"You thought you spied a fruit, but were unable to procure any.",
"You climb all over that tree and don't find a single pickable",
"You wouldn't steal a fruit from a tree with no fruit.",
"Are you sure there aren't any fruit just lying around on the ground that you can /take?"
];

View File

@ -0,0 +1,15 @@
import Command from "@server/commands/Command";
import { getFruitCount } from "@server/fish/tree";
export const tree = new Command(
"tree",
["tree", "troo", "truu", "traa"],
"Check how many fruit are on the Kekklefruit Tree.",
"tree",
"command.fishing.tree",
async ({ id, command, args, prefix, part, user, isDM }) => {
const num = await getFruitCount();
return `Friend ${part.name}: ${num}`;
}
);

View File

@ -19,6 +19,8 @@ import { autofish } from "./util/autofish";
import { pokedex } from "./util/pokedex";
import { myid } from "./general/myid";
import { yeet } from "./inventory/yeet";
import { tree } from "./fishing/tree";
import { pick } from "./fishing/pick";
interface ICommandGroup {
id: string;
@ -39,7 +41,7 @@ commandGroups.push(generalGroup);
const fishingGroup: ICommandGroup = {
id: "fishing",
displayName: "Fishing",
commands: [fish, reel, location, go, nearby, look]
commands: [fish, reel, location, go, nearby, look, tree, pick]
};
commandGroups.push(fishingGroup);

View File

@ -0,0 +1,13 @@
import Command from "@server/commands/Command";
export const group = new Command(
"group",
["group"],
"Get user group",
"group",
"command.util.group",
async props => {
return JSON.stringify(props);
},
false
);

View File

@ -3,6 +3,8 @@ import type Command from "./Command";
import { commandGroups } from "./groups";
import { createUser, getUser, updateUser } from "@server/data/user";
import { createInventory, getInventory } from "@server/data/inventory";
import { getUserGroup } from "@server/data/permissions";
import { groupHasPermission } from "@server/permissions/groups";
export const logger = new Logger("Command Handler");
@ -52,7 +54,10 @@ export async function handleCommand(
let inventory = await getInventory(user.inventoryId);
if (!inventory) inventory = await createInventory({ id: user.inventoryId });
// TODO Check user's (or their groups') permissions against command permission node
const group = await getUserGroup(user.id);
if (!group) return;
if (!groupHasPermission(group.groupId, foundCommand.permissionNode))
return { response: `No permission.` };
try {
const response = await foundCommand.callback({

View File

@ -0,0 +1,44 @@
import type { User } from "@prisma/client";
import prisma from "./prisma";
export async function setUserGroup(userID: User["id"], groupID: string) {
const existing = await getUserGroup(userID);
if (!existing) createUserGroup(userID, "default");
return await prisma.userPermission.update({
where: {
userId: userID,
groupId: groupID
},
data: {
groupId: groupID,
userId: userID
}
});
}
export async function getUserGroup(userID: User["id"]) {
const existing = await prisma.userPermission.findUnique({
where: {
userId: userID
}
});
if (existing) return existing;
await createUserGroup(userID, "default");
return await prisma.userPermission.findUnique({
where: {
userId: userID
}
});
}
export async function createUserGroup(userID: User["id"], groupID: string) {
return await prisma.userPermission.create({
data: {
userId: userID,
groupId: groupID
}
});
}

View File

@ -35,6 +35,14 @@ export const locations = loadConfig<ILocation[]>("config/locations.yml", [
nearby: ["pond", "lake", "river"],
hasSand: true,
objects: []
},
{
id: "forest",
name: "Forest",
nearby: ["pond", "lake", "beach"],
hasSand: false,
objects: []
}
]);

51
src/api/fish/tree.ts Normal file
View File

@ -0,0 +1,51 @@
import { createKeyValueStore, kvGet, kvSet } from "@server/data/keyValueStore";
import { addTickEvent } from "@util/tick";
const key = "tree";
export async function getFruitCount() {
return await kvGet(key);
}
export async function setFruitCount(num: number) {
await kvSet(key, num);
}
export async function treeTick() {
const r = Math.random();
if (r < 0.00001) {
await growFruit(5);
} else if (r < 0.0001) {
await growFruit(1);
}
}
export async function initTree() {
const num = await kvGet(key);
if (typeof num !== "number") kvSet(key, 0);
addTickEvent(treeTick);
}
export async function genFruitAndRemove(): Promise<IItem> {
await growFruit(-1);
return {
id: "kekklefruit",
name: "Kekklefruit",
objtype: "item",
emoji: "🍍"
};
}
export async function hasFruit() {
const num = await getFruitCount();
if (num <= 0) return false;
return true;
}
export async function growFruit(num: number) {
const old = await getFruitCount();
await setFruitCount(old + num);
}

View File

@ -2,6 +2,8 @@ import "./api/server";
import "./cli/readline";
import { startFisherTick } from "./fish/fishers";
import { startObjectTimers } from "./fish/locations";
import { initTree } from "./fish/tree";
startObjectTimers();
await startFisherTick();
await initTree();

View File

@ -0,0 +1,73 @@
import { Logger } from "@util/Logger";
import { loadConfig } from "@util/config";
const logger = new Logger("Permission Handler");
export const groups = loadConfig<IGroup[]>("config/permissions.yml", [
{
id: "default",
permissions: [
"command.general.*",
"command.fishing.*",
"command.inventory.*",
"command.util.*"
]
},
{
id: "owner",
permissions: ["*"]
}
]);
groups.sort((a, b) => a.id.localeCompare(b.id));
export function findGroup(
id: string,
index: number = Math.floor(groups.length / 2),
rec: number = 0
) {
// let num = groups[index].id.localeCompare(id);
// if (groups[index].id == id) return groups[index];
// rec++;
// if (num > 1) {
// findGroup(id, Math.floor(index / 2), rec);
// } else if (num < 1) {
// findGroup(id, Math.floor(index / 2) + index, rec);
// }
// logger.debug("Here 2");
return groups.find(g => g.id == id);
}
export function groupHasPermission(groupID: IGroup["id"], handle: string) {
const group = findGroup(groupID);
if (!group) return false;
for (const permission of group.permissions) {
if (checkPermission(handle, permission)) return true;
}
}
export function checkPermission(p1: string, p2: string) {
const ps1 = p1.split(".");
const ps2 = p2.split(".");
for (let i = 0; i < ps1.length; i++) {
if (ps1[i] == ps2[i]) {
if (i == ps1.length - 1 || i == ps2.length - 1) {
return true;
} else {
continue;
}
}
if (ps1[i] == "*") return true;
if (ps2[i] == "*") return true;
return false;
}
return false;
}

View File

@ -0,0 +1,9 @@
import type { User } from "@prisma/client";
import { getUserGroup } from "@server/data/permissions";
export async function hasPermission(userID: User["id"], handle: string) {
const dbgroup = await getUserGroup(userID);
if (!dbgroup) return false;
dbgroup.groupId;
return false;
}

View File

@ -64,7 +64,7 @@ rl.on("line", async line => {
if (!command) return;
if (command.response) {
logger.info(cliMd(command.response));
logger.info(cliMd(command.response.split("\n").join("\n\n")));
}
});

5
src/util/types.d.ts vendored
View File

@ -123,3 +123,8 @@ interface IItemBehaviorData {
type TItemBehavior = Behavior<IItemBehaviorData>;
type TItemBehaviorMap = TBehaviorMap<TItemBehavior>;
interface IGroup {
id: string;
permissions: string[];
}