BIG UPDATE: Plants and mutations moved to database. Fetchable with API.

This commit is contained in:
sarah committed 2026-08-31 19:26:25 +02:00
1 parent 5e6e376d8e
commit dde47ff5a6
7 files changed
+272 -228

No files matched your search

Executable → Regular
View File
File mode changed.
+71 -31
View File
@@ -1,54 +1,90 @@
const MutationTimeFeePerMinute = 15;
const MutationTimeFeePerMinute = 3;
const PlantKeysById = new Map();
const PlantsById = new Map();
const MutationsById = new Map();
let IndexedPlants = null;
let IndexedMutations = null;
for (
const [PlantKey, Plant]
of Object.entries(Plants)
) {
if (PlantsById.has(Plant.Id)) {
throw new Error(
"Duplicate plant ID: " +
Plant.Id
function EnsureEconomyIndexes() {
if (
IndexedPlants === Plants &&
IndexedMutations ===
MutationSets
) {
return;
}
PlantKeysById.clear();
PlantsById.clear();
MutationsById.clear();
for (
const [PlantKey, Plant]
of Object.entries(Plants)
) {
if (
PlantsById.has(
Plant.Id
)
) {
throw new Error(
"Duplicate plant ID: " +
Plant.Id
);
}
PlantKeysById.set(
Plant.Id,
PlantKey
);
PlantsById.set(
Plant.Id,
Plant
);
}
PlantKeysById.set(
Plant.Id,
PlantKey
);
PlantsById.set(
Plant.Id,
Plant
);
}
for (
const Mutation
of Object.values(
MutationSets
)
) {
if (
MutationsById.has(
Mutation.Id
)
) {
throw new Error(
"Duplicate mutation ID: " +
Mutation.Id
);
}
for (
const Mutation
of Object.values(MutationSets)
) {
if (MutationsById.has(Mutation.Id)) {
throw new Error(
"Duplicate mutation ID: " +
Mutation.Id
MutationsById.set(
Mutation.Id,
Mutation
);
}
MutationsById.set(
Mutation.Id,
Mutation
);
IndexedPlants = Plants;
IndexedMutations =
MutationSets;
}
function GetPlantKeyById(
PlantId
) {
EnsureEconomyIndexes();
return PlantKeysById.get(
Number(PlantId)
) ?? null;
@@ -58,6 +94,8 @@ function GetPlantKeyById(
function GetPlantById(
PlantId
) {
EnsureEconomyIndexes();
return PlantsById.get(
Number(PlantId)
) ?? null;
@@ -67,6 +105,8 @@ function GetPlantById(
function GetMutationById(
MutationId
) {
EnsureEconomyIndexes();
return MutationsById.get(
Number(MutationId)
) ?? null;
+16
View File
@@ -8,6 +8,22 @@ const GardenUpdateInterval = 1000;
async function StartGame() {
try {
await LoadGameContent();
} catch (Error) {
console.error(
"Couldn't load Garden content:",
Error
);
SetGardenMessage(
"Couldn't load plant or mutation data."
);
return;
}
GameSave = await LoadGame();
BindGardenTools();
+97 -110
View File
@@ -1,114 +1,101 @@
const MutationSets = {
RoseDarkening: {
Id: 1,
Name: "Rose darkening",
let MutationSets = {};
Description:
"A mutation that seems to corrupt roses.",
let MutationsLoadPromise = null;
let GameContentLoadPromise = null;
Priority: 10,
Rotation: "Any",
Chance: 0.1,
Cooldown: 120000,
Relations: {
PlantsUsed: [
1
],
PlantsCreated: [
2
]
},
Pattern: [
[
{
Tags: ["Rose"],
Capture: "ParentA"
},
"Empty"
],
[
"Empty",
{
Tags: ["Rose"],
Capture: "ParentB"
}
]
],
Success: [
[
"Empty",
"DarkRose"
],
[
"DarkRose",
"Empty"
]
],
Failure: "Keep"
},
RoseDyePurple: {
Id: 2,
Name: "Rose dying purple",
Description:
"A colourful mutation that makes a purple rose.",
Priority: 20,
Rotation: "Any",
Chance: 1.0,
Cooldown: 100000,
Relations: {
PlantsUsed: [
1,
3
],
PlantsCreated: [
4
]
},
Pattern: [
[
{
Tags: [
"Rose",
"Red"
],
Capture: "ParentA"
},
"Empty",
{
Tags: [
"Rose",
"Blue"
],
Capture: "ParentB"
}
]
],
Success: [
[
"Empty",
"PurpleRose",
"Empty"
]
],
Failure: "Keep"
async function LoadMutations() {
if (MutationsLoadPromise !== null) {
return MutationsLoadPromise;
}
};
MutationsLoadPromise =
LoadMutationsFromApi();
try {
return await MutationsLoadPromise;
} catch (Error) {
MutationsLoadPromise = null;
throw Error;
}
}
async function LoadMutationsFromApi() {
const Response =
await fetch(
ApiUrl + "/Mutations.php",
{
method: "GET",
headers: {
"Accept":
"application/json"
}
}
);
if (!Response.ok) {
throw new Error(
"Mutations API returned HTTP " +
Response.status
);
}
const Result =
await Response.json();
if (
!Result.Success ||
Result.Mutations === null ||
typeof Result.Mutations !==
"object" ||
Array.isArray(
Result.Mutations
)
) {
throw new Error(
Result.Error ??
"Mutations API returned invalid data."
);
}
MutationSets =
Result.Mutations;
return MutationSets;
}
async function LoadGameContent() {
if (GameContentLoadPromise === null) {
GameContentLoadPromise =
Promise.all([
LoadPlants(),
LoadMutations()
]);
}
try {
await GameContentLoadPromise;
} catch (Error) {
GameContentLoadPromise = null;
throw Error;
}
return {
Plants: Plants,
Mutations: MutationSets
};
}
+70 -87
View File
@@ -1,91 +1,74 @@
const Plants = {
RedRose: {
Id: 1,
Name: "Red Rose",
let Plants = {};
Description:
"A common red rose.",
let PlantsLoadPromise = null;
Tags: [
"Rose",
"Flower",
"Red"
],
GrowthTime: 3600000,
Effects: [],
Shop: {
ShopPlant: true,
BaseCost: 10
}
},
DarkRose: {
Id: 2,
Name: "Dark Rose",
Description:
"A jet-black rose.",
Tags: [
"Rose",
"Flower",
"Black"
],
GrowthTime: 4000000,
Effects: [],
Shop: {
ShopPlant: false
}
},
BlueRose: {
Id: 3,
Name: "Blue Rose",
Description:
"An uncommon blue rose.",
Tags: [
"Rose",
"Flower",
"Blue"
],
GrowthTime: 3600000,
Effects: [],
Shop: {
ShopPlant: true,
BaseCost: 15
}
},
PurpleRose: {
Id: 4,
Name: "Purple Rose",
Description:
"A rare purple rose.",
Tags: [
"Rose",
"Flower",
"Purple"
],
GrowthTime: 3600000,
Effects: [],
Shop: {
ShopPlant: false
}
async function LoadPlants() {
if (PlantsLoadPromise !== null) {
return PlantsLoadPromise;
}
};
PlantsLoadPromise =
LoadPlantsFromApi();
try {
return await PlantsLoadPromise;
} catch (Error) {
PlantsLoadPromise = null;
throw Error;
}
}
async function LoadPlantsFromApi() {
const Response =
await fetch(
ApiUrl + "/Plants.php",
{
method: "GET",
headers: {
"Accept":
"application/json"
}
}
);
if (!Response.ok) {
throw new Error(
"Plants API returned HTTP " +
Response.status
);
}
const Result =
await Response.json();
if (
!Result.Success ||
Result.Plants === null ||
typeof Result.Plants !==
"object" ||
Array.isArray(
Result.Plants
)
) {
throw new Error(
Result.Error ??
"Plants API returned invalid data."
);
}
Plants =
Result.Plants;
return Plants;
}
+2
View File
@@ -5,6 +5,8 @@ async function StartProfile() {
await RenderProfilePlayer();
try {
await LoadGameContent();
ProfileSave =
await LoadGame();
+16
View File
@@ -3,6 +3,22 @@ let ShopPurchasePending = false;
async function StartShop() {
try {
await LoadGameContent();
} catch (Error) {
console.error(
"Couldn't load Shop content:",
Error
);
SetShopMessage(
"Couldn't load plant or mutation data."
);
return;
}
ShopSave = await LoadGame();
RenderShop();