add first patch

This commit is contained in:
2026-07-31 10:34:32 +09:00
parent 03aac2e45e
commit b1cbc6c78d
6390 changed files with 547430 additions and 0 deletions
@@ -0,0 +1,649 @@
console.info("[SOCIETY] artisanHopper.js loaded");
const artisanMachineCanHaveAdditionalOutput = [
"society:loom",
"society:crystalarium",
"society:seed_maker",
"society:aging_cask",
"society:mayonnaise_machine",
"society:wine_keg"
];
/**
* @param {Internal.Stages|SocietyStages} stages
*/
global.handleAdditionalArtisanMachineOutputs = (
level,
block,
artisanMachine,
recipes,
recipeId,
upgraded,
stages
) => {
switch (artisanMachine.id) {
case "society:loom": {
if (upgraded && rnd25()) {
global.insertBelow(
level,
block,
Ingredient.of("#society:loot_furniture").itemIds[
Math.floor(
Math.random() *
Ingredient.of("#society:loot_furniture").itemIds.length
)
]
);
}
break;
}
case "society:crystalarium": {
if (upgraded && rnd10()) {
let recipe = recipes.get(recipeId);
if (!recipe) {
let legacyType = artisanMachine.getEntityData().data.type;
if (legacyType > 0) {
let legacyKey = Array.from(recipes.keys())[Number(legacyType) - 1];
recipe = recipes.get(legacyKey);
}
}
if (recipe && recipe.output) {
recipe.output.forEach((item) => {
const pristinePath = String(Item.of(item).id).split(":")[1];
if (pristinePath) {
global.insertBelow(level, block, `society:pristine_${pristinePath}`);
}
});
}
}
break;
}
case "society:seed_maker": {
if (upgraded && rnd5()) {
global.insertBelow(level, block, "society:ancient_fruit_seed");
}
break;
}
case "society:aging_cask": {
if (stages.has("aged_prize") && rnd5()) {
global.insertBelow(level, block, "society:prize_ticket");
}
break;
}
case "society:wine_keg": {
if (upgraded && rnd5()) {
global.insertBelow(level, block, "society:relic_trove");
}
break;
}
case "society:mayonnaise_machine": {
if (upgraded && rnd5()) {
global.insertBelow(level, block, "society:supreme_mayonnaise");
}
break;
}
}
};
// TODO: make artisan hopper set tappers
/**
* @param {Internal.Stages|SocietyStages} stages
*/
global.getArtisanMachineData = (player, block, upgraded, stages) => {
let machineData = {
recipes: [],
stageCount: 0,
multipleInputs: false,
hasTag: false,
outputMult: 1,
soundType: "minecraft:ui.toast.in",
};
let rancherOutputCount;
if (stages.has("rancher") && Math.random() <= 0.2) {
rancherOutputCount = 2;
}
let machineNbt = block.getEntityData();
switch (block.id) {
case "society:loom":
machineData = {
recipes: global.loomRecipes,
stageCount: 5,
multipleInputs: true,
hasTag: true,
outputMult: rancherOutputCount,
soundType: "minecraft:block.wool.fall",
};
break;
case "society:mayonnaise_machine":
machineData = {
recipes: global.mayonnaiseMachineRecipes,
stageCount: 3,
outputMult: rancherOutputCount,
soundType: "minecraft:block.sniffer_egg.plop",
};
break;
case "society:preserves_jar":
machineData = {
recipes: global.preservesJarRecipes,
stageCount: upgraded ? 3 : 5,
multipleInputs: true,
soundType: "minecraft:block.wood.place",
};
break;
case "society:crystalarium":
machineData = {
recipes: global.crystalariumCrystals,
stageCount: 5,
soundType: "minecraft:block.amethyst_block.step",
};
break;
case "society:wine_keg":
machineData = {
recipes: global.wineKegRecipes,
stageCount: 3,
multipleInputs: true,
soundType: "minecraft:block.wood.place",
};
break;
case "society:aging_cask":
machineData = {
recipes: global.agingCaskRecipes,
stageCount: 10,
soundType: "minecraft:block.wood.place",
};
break;
case "society:cheese_press":
machineData = {
recipes: global.cheesePressRecipes,
stageCount: 2,
outputMult: rancherOutputCount,
soundType: "species:block.frozen_meat.place",
};
break;
case "society:ancient_cask":
if (stages.has("ancient_aging")) {
if (upgraded) {
machineData = {
recipes: global.ancientCaskRecipes,
stageCount: 4,
multipleInputs: true,
hasTag: false,
outputMult: 4,
soundType: "",
};
} else
machineData = {
recipes: global.ancientCaskRecipes,
stageCount: 20,
soundType: "minecraft:block.wood.place",
};
} else machineData = undefined;
break;
case "society:dehydrator":
machineData = {
recipes: global.dehydratorRecipes,
stageCount: 8,
multipleInputs: true,
soundType: "species:block.alphacene_foliage.place",
};
break;
case "society:deluxe_worm_farm":
machineData = {
recipes: global.deluxeWormFarmRecipes,
stageCount: 4,
multipleInputs: true,
soundType: "aquaculture:fish_flop",
};
break;
case "society:seed_maker":
machineData = {
recipes: global.seedMakerRecipes,
stageCount: 3,
multipleInputs: true,
soundType: "unusualfishmod:crab_scuttling",
};
break;
case "society:fish_smoker":
machineData = {
recipes: global.fishSmokerRecipes,
stageCount: 5,
outputMult: upgraded ? 2 : 1,
soundType: "farmersdelight:block.skillet.add_food",
};
break;
case "society:espresso_machine":
machineData = {
recipes: global.espressoMachineRecipes,
stageCount: 4,
multipleInputs: true,
soundType: "doapi:brewstation_whistle",
};
break;
case "society:bait_maker":
machineData = {
recipes: global.baitMakerRecipes,
stageCount: 1,
soundType: "aquaculture:fish_death",
};
break;
case "society:recycling_machine":
machineData = {
recipes: global.recyclingMachineRecipes,
stageCount: 1,
soundType: "twigs:block.basalt_bricks.fall",
outputMult: upgraded ? 2 : 1,
};
break;
case "society:oil_maker":
machineData = {
recipes: global.oilMakerRecipes,
stageCount: 1,
soundType: "supplementaries:block.jar.place",
};
break;
case "society:tapper":
machineData = {
recipes: global.tapperRecipes,
stageCount: 1,
soundType: "vinery:cabinet_close",
outputMult: stages.has("canadian_and_famous") ? 2 : 1,
};
break;
case "society:mushroom_log":
machineData = {
recipes: global.mushroomLogRecipes,
stageCount: 1,
soundType: "species:block.alphacene_moss.place",
outputMult: machineNbt && machineNbt.data && machineNbt.data.baseCount ? machineNbt.data.baseCount : 1,
};
break;
case "society:charging_rod":
machineData = { recipes: null, stageCount: 5, soundType: "" };
break;
default:
machineData = undefined;
}
return machineData;
};
/**
* @param {Internal.BlockEntityJS} artisanHopper
* @param {Internal.Player|null} player
*/
global.runArtisanHopper = (artisanHopper, artisanMachinePos, player, delay) => {
const { level, block, inventory } = artisanHopper;
const server = level.server;
server.scheduleInTicks(delay, () => {
const artisanMachine = level.getBlock(artisanMachinePos);
const { x, y, z } = artisanMachine;
const nbt = artisanMachine.getEntityData();
if (!nbt || !nbt.data) return;
const upgraded = artisanMachine.properties.get("upgraded") == "true";
const stages = global.getBlockEntityStages(artisanHopper);
const loadedData = global.getArtisanMachineData(
player,
artisanMachine,
upgraded,
stages,
);
const season = global.getSeasonFromLevel(level);
const chargingRodOutput = Item.of(
`${upgraded && season === "winter" ? 3 : 1}x society:battery`
);
if (loadedData && artisanMachine) {
let {
recipes,
stageCount,
multipleInputs,
hasTag,
outputMult,
soundType,
} = loadedData;
if (recipes) {
global.convertFromLegacy(recipes, level, artisanMachine);
}
let refreshedNbt = artisanMachine.getEntityData();
let { stage, recipe } = refreshedNbt.data;
let currentStage = stage || 0;
let resolvedRecipeId = recipe;
if (recipes && !recipes.has(resolvedRecipeId)) {
let legacyType = refreshedNbt.data.type;
if (legacyType > 0) {
let legacyKey = Array.from(recipes.keys())[Number(legacyType) - 1];
if (legacyKey) resolvedRecipeId = legacyKey;
}
}
let hasInfinityWorm =
artisanMachine.id === "society:deluxe_worm_farm" && upgraded;
let machineOutputs = [];
let newProperties = artisanMachine.getProperties();
let recycleSparkstone;
if (
newProperties.get("mature").toLowerCase() === "true" &&
(artisanMachine.id === "society:charging_rod"
? global.inventoryBelowHasRoom(level, block, chargingRodOutput)
: recipes.has(resolvedRecipeId) &&
global.inventoryBelowHasRoomForAll(
level,
block,
recipes.get(resolvedRecipeId).output
)) &&
global.hasInventoryItems(inventory, "society:sparkstone", 1)
) {
server.runCommandSilent(
`playsound stardew_fishing:dwop block @a ${x} ${y} ${z}`
);
if (artisanMachine.id === "society:charging_rod") {
machineOutputs.push(chargingRodOutput);
artisanMachine.set(artisanMachine.id, {
working: false,
mature: false,
upgraded: upgraded,
stage: "0",
});
} else if (hasInfinityWorm) {
machineOutputs.push(
Item.of("4x crabbersdelight:deluxe_crab_trap_bait")
);
artisanMachine.set(artisanMachine.id, {
facing: artisanMachine.properties.get("facing"),
type: "1",
working: true,
mature: false,
upgraded: upgraded,
stage: "0",
});
} else {
machineOutputs = global.artisanHarvest(
artisanMachine,
recipes,
stageCount,
outputMult,
artisanMachine.id === "society:cheese_press",
true
);
}
if (machineOutputs && machineOutputs.length > 0) {
recycleSparkstone = global.checkSparkstoneRecyclers(level, block);
if (
artisanMachine.id === "society:dehydrator" &&
upgraded &&
global.dehydratableMushroomOutputs.includes(machineOutputs[0].id)
) {
machineOutputs.forEach((output) => {
output.count = 2;
});
}
if (
artisanMachineCanHaveAdditionalOutput.includes(artisanMachine.id)
) {
global.handleAdditionalArtisanMachineOutputs(
level,
block,
artisanMachine,
recipes,
resolvedRecipeId,
upgraded,
stages
);
}
let sparkstoneSaveChance = 0;
if (stages.has("slouching_towards_artistry")) {
sparkstoneSaveChance = Number(currentStage) * 0.05;
}
if (!recycleSparkstone && Math.random() > sparkstoneSaveChance) {
global.useInventoryItems(inventory, "society:sparkstone", 1);
} else {
level.spawnParticles(
"species:youth_potion",
true,
x,
y + 0.5,
z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
}
machineOutputs.forEach((output) => {
global.insertBelow(level, block, output);
});
level.spawnParticles(
"species:ascending_dust",
true,
x,
y + 1,
z,
0.2 * rnd(1, 1.5),
0.2 * rnd(1, 1.5),
0.2 * rnd(1, 1.5),
3,
0.01
);
}
}
let abovePos = block.getPos().above();
let aboveBlock = level.getBlock(abovePos.x, abovePos.y, abovePos.z);
if (
recipes &&
newProperties.get("working").toLowerCase() === "false" &&
global.hasInventoryItems(inventory, "society:sparkstone", 1) &&
aboveBlock.inventory &&
!aboveBlock.inventory.isEmpty()
) {
let aboveBlockData = aboveBlock.getEntityData();
if (aboveBlockData && aboveBlockData.toString().includes("filter_upgrade")) {
if (player) {
player.tell(Text.translatable("block.society.artisan_hopper.filter").red());
}
return;
}
let slots = aboveBlock.inventory.getSlots();
let slotStack;
let outputCount;
for (let i = 0; i < slots; i++) {
slotStack = aboveBlock.inventory.getStackInSlot(i);
if (
!(
multipleInputs &&
!slotStack.isEmpty() &&
slotStack.count < stageCount
)
) {
outputCount = global.artisanInsert(
artisanMachine,
slotStack,
level,
recipes,
stageCount,
soundType,
multipleInputs,
hasTag,
true,
server
);
if (outputCount > 0) {
recycleSparkstone = global.checkSparkstoneRecyclers(level, block);
if (!recycleSparkstone)
global.useInventoryItems(inventory, "society:sparkstone", 1);
else {
level.spawnParticles(
"species:youth_potion",
true,
x,
y + 0.5,
z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
}
level.runCommandSilent(
`playsound create:fwoomp block @a ${x} ${y} ${z} 0.8`
);
aboveBlock.inventory.extractItem(i, outputCount, false);
break;
}
}
}
}
if (
hasInfinityWorm &&
newProperties.get("working").toLowerCase() === "false"
) {
artisanMachine.set(artisanMachine.id, {
facing: artisanMachine.properties.get("facing"),
type: "1",
working: true,
mature: false,
upgraded: upgraded,
stage: "0",
});
}
}
});
};
/**
* @param {Internal.BlockEntityJS} entity
*/
global.artisanHopperScan = (entity, radius) => {
const { block, level } = entity;
const { x, y, z } = block;
const attachedPlayer = global.cacheOwner(entity, [
"slouching_towards_artistry", "ancient_aging", "rancher", "aged_prize", "canadian_and_famous"
]);
let scanBlock;
let scannedBlocks = 0;
for (let pos of BlockPos.betweenClosed(
new BlockPos(x - radius, y - radius, z - radius),
[x + radius, y + radius, z + radius]
)) {
if (!level.isLoaded(pos)) continue;
scanBlock = level.getBlock(pos);
if (scanBlock.hasTag("society:artisan_machine")) {
global.runArtisanHopper(
entity,
pos.immutable(),
attachedPlayer,
scannedBlocks * 5
);
scannedBlocks++;
}
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:artisan_hopper", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.artisan_hopper.description").gray()
);
item.tooltip(
Text.translatable(
"society.working_block_entity.apply_player_skill"
).gray()
);
item.tooltip(Text.translatable("tooltip.society.area", `7x7x7`).green());
item.tooltip(
Text.translatable(
"block.society.artisan_hopper.description.fuel"
).lightPurple()
);
item.modelJson({
parent: "society:block/kubejs/artisan_hopper",
});
})
.soundType("copper")
.model("society:block/kubejs/artisan_hopper")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 2);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(600, 0, (entity) => {
global.artisanHopperScan(entity, 3);
});
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.insertItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.insertItem(slot, stack, simulate)
)
.extractItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.extractItem(slot, stack, simulate)
)
.getSlotLimit((blockEntity, slot) =>
blockEntity.inventory.getSlotLimit(slot)
)
.getSlots((blockEntity) => blockEntity.inventory.slots)
.getStackInSlot((blockEntity, slot) =>
blockEntity.inventory.getStackInSlot(slot)
)
);
});
});
StartupEvents.registry("block", (event) => {
event
.create("society:mini_artisan_hopper", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.artisan_hopper.description").gray()
);
item.tooltip(
Text.translatable(
"society.working_block_entity.apply_player_skill"
).gray()
);
item.tooltip(Text.translatable("tooltip.society.area", `3x3x3`).green());
item.tooltip(
Text.translatable(
"block.society.artisan_hopper.description.fuel"
).lightPurple()
);
item.modelJson({
parent: "society:block/kubejs/mini_artisan_hopper",
});
})
.soundType("copper")
.model("society:block/kubejs/mini_artisan_hopper")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 2);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(600, 0, (entity) => {
global.artisanHopperScan(entity, 1);
});
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.insertItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.insertItem(slot, stack, simulate)
)
.extractItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.extractItem(slot, stack, simulate)
)
.getSlotLimit((blockEntity, slot) =>
blockEntity.inventory.getSlotLimit(slot)
)
.getSlots((blockEntity) => blockEntity.inventory.slots)
.getStackInSlot((blockEntity, slot) =>
blockEntity.inventory.getStackInSlot(slot)
)
);
});
});