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)
)
);
});
});
@@ -0,0 +1,342 @@
console.info("[SOCIETY] autoGrabber.js loaded");
const handleAutoGrabSpecialItem = (
data,
day,
chance,
hungry,
minHearts,
mult,
item,
hasQuality,
plushieModifiers,
e
) => {
const { player, target, level, server, block, inventory } = e;
let affection;
let mood;
let recycleSparkstone;
let resolvedItem = item;
let resolvedChance = chance;
let resolvedHasQuality = hasQuality
let dropAmount = mult * (plushieModifiers && plushieModifiers.doubleDrops ? 2 : 1);
if (plushieModifiers) {
affection = 1000;
mood = 256;
resolvedChance = chance + plushieModifiers.probabilityIncrease;
if (plushieModifiers.processItems) {
let processOutput = global.getProcessedItem(item, dropAmount);
resolvedItem = processOutput.item.id;
dropAmount = Math.round(dropAmount / processOutput.divisor) * processOutput.item.count;
resolvedHasQuality = processOutput.preserveQuality
}
} else {
affection = data.getInt("affection") || 0;
mood = global.getOrFetchMood(level, target, day, player);
}
let hearts = Math.floor(affection / 100);
let quality = 0;
if (
(!hungry || plushieModifiers) &&
hearts >= minHearts &&
Math.random() <= resolvedChance
) {
if (item.includes("large") && Math.random() > (mood + hearts * 10) / 256) {
return;
}
if (resolvedHasQuality && mood >= 160) {
quality = global.getHusbandryQuality(hearts, mood);
}
let remaining = dropAmount;
let specialItemResultCode = 1;
while (remaining > 0 && specialItemResultCode == 1) {
let currentAmount = Math.min(remaining, 64);
let specialItem = Item.of(`${currentAmount}x ${resolvedItem}`, quality > 0 ? `{quality_food:{effects:[],quality:${quality}}}` : null);
specialItemResultCode = global.insertBelow(level, block, specialItem);
remaining -= currentAmount;
}
if (specialItemResultCode == 1) {
recycleSparkstone = global.checkSparkstoneRecyclers(level, block);
if (!recycleSparkstone && global.useInventoryItems(inventory, "society:sparkstone", 1) != 1)
console.error("Sparkstone not consumed when it should have been!");
server.runCommandSilent(
`playsound stardew_fishing:dwop block @a ${block.x} ${block.y} ${block.z}`
);
if (target.x) {
level.spawnParticles(
"farmersdelight:star",
true,
target.x,
target.y + 1,
target.z,
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
3,
0.01
);
}
}
}
};
/**
* @param {Internal.BlockEntityJS} autoGrabber
* @param {Internal.Player|null} player
*/
global.autoGrabAnimal = (autoGrabber, player, animal, plushieModifiers) => {
const { inventory, block, level } = autoGrabber;
let recycleSparkstone;
let data;
let nbt;
if (plushieModifiers) {
nbt = animal.getEntityData();
data = nbt.data.animal;
} else {
data = animal.persistentData;
}
const stages = global.getBlockEntityStages(autoGrabber);
const day = global.getDay(level);
let mood;
let hungry;
if (plushieModifiers) {
hungry = false;
mood = 256;
} else {
hungry = global.compareDay(day, data.getInt("ageLastFed"), 1);
if (!(!global.compareDay(day, data.getInt("ageLastPet"), 1) || level.dayTime() % 24000 > 12000)) return;
mood = global.getOrFetchMood(level, animal, day, player);
}
if (mood < 64 && Math.random() < mood / 64) return;
if (!hungry) {
if (
(plushieModifiers
? global.milkableAnimals.includes(data.type)
: global.checkEntityTag(animal, "society:milkable_animal")) &&
global.inventoryHasItems(inventory, "society:sparkstone", 1) == 1
) {
let milkItem = global.getMilk(
level,
plushieModifiers ? data : animal,
data,
player,
day,
false,
plushieModifiers,
stages,
);
if (milkItem !== -1) {
let insertedMilk = global.insertBelow(level, block, milkItem) == 1;
if (insertedMilk) {
recycleSparkstone = global.checkSparkstoneRecyclers(level, block);
if (!recycleSparkstone && global.useInventoryItems(inventory, "society:sparkstone", 1) != 1)
console.error("Sparkstone not consumed when it should have been!");
if (!plushieModifiers && !global.getAnimalIsNotCramped(animal, 1.1))
data.affection = data.getInt("affection") - 50;
level.server.runCommandSilent(
`playsound minecraft:entity.cow.milk block @a ${animal.x} ${animal.y} ${animal.z}`
);
level.spawnParticles(
"atmospheric:aloe_blossom",
true,
animal.x,
animal.y + 1.5,
animal.z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
if (plushieModifiers && !plushieModifiers.resetDay) {
nbt.merge({
data: {
animal: {
ageLastMilked: day,
},
},
});
animal.setEntityData(nbt);
}
}
}
}
if (global.inventoryHasItems(inventory, "society:sparkstone", 1) == 1) {
global.handleSpecialHarvest(
level,
plushieModifiers ? data : animal,
player,
level.server,
block,
inventory,
plushieModifiers,
handleAutoGrabSpecialItem,
stages,
);
if (plushieModifiers && !plushieModifiers.resetDay) {
nbt.merge({
data: {
animal: {
ageLastDroppedSpecial: day,
},
},
});
animal.setEntityData(nbt);
}
}
if (
level.getBlock(block.pos).getProperties().get("upgraded") === "true" &&
global.inventoryHasItems(inventory, "society:sparkstone", 1) == 1
) {
let droppedLoot = global.getMagicShearsOutput(
level,
plushieModifiers ? data : animal,
player,
plushieModifiers,
stages,
);
if (droppedLoot !== -1) {
level.server.runCommandSilent(
`playsound minecraft:entity.sheep.shear block @a ${block.x} ${block.y} ${block.z}`
);
let insertedMagicDrops = false;
for (let i = 0; i < droppedLoot.length; i++) {
insertedMagicDrops =
global.insertBelow(level, block, droppedLoot[i]) == 1;
}
if (insertedMagicDrops) {
recycleSparkstone = global.checkSparkstoneRecyclers(level, block);
if (!recycleSparkstone && global.useInventoryItems(inventory, "society:sparkstone", 1) != 1)
console.error("Sparkstone not consumed when it should have been!");
if (!plushieModifiers && !global.getAnimalIsNotCramped(animal, 1.1))
data.affection = data.getInt("affection") - 50;
}
}
}
}
};
/**
* @param {Internal.BlockEntityJS} entity
* @param {Internal.Player|null} attachedPlayer
*/
global.runAutoGrabber = (entity, attachedPlayer) => {
const { block, level } = entity;
let radius = 5;
let nearbyFarmAnimals;
nearbyFarmAnimals = level
.getEntitiesWithin(AABB.ofBlock(block).inflate(radius))
.filter((entity) =>
global.checkEntityTag(entity, "society:husbandry_animal")
);
nearbyFarmAnimals.forEach((animal) => {
global.autoGrabAnimal(entity, attachedPlayer, animal);
});
let { x, y, z } = block;
let scanBlock;
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:plushies")) {
let nbt = scanBlock.getEntityData();
if (nbt.data.animal) {
global.autoGrabAnimal(
entity,
attachedPlayer,
scanBlock,
global.getPlushieModifiers(level, nbt.data, scanBlock)
);
}
}
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:auto_grabber", "cardinal")
.displayName("Auto-Grabber")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 0, 16, 30, 16)
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.auto_grabber.description").gray()
);
item.tooltip(
Text.translatable(
"society.working_block_entity.apply_player_skill"
).gray()
);
item.tooltip(
Text.translatable(
"block.society.auto_grabber.description.upgrade"
).gold()
);
item.tooltip(
Text.translatable("tooltip.society.area", `11x11x11`).green()
);
item.tooltip(
Text.translatable(
"block.society.auto_grabber.description.fuel"
).lightPurple()
);
item.modelJson({
parent: "society:block/kubejs/auto_grabber",
});
})
.model("society:block/kubejs/auto_grabber")
.property(booleanProperty.create("upgraded"))
.defaultState((state) => {
state.set(booleanProperty.create("upgraded"), false);
})
.placementState((state) => {
state.set(booleanProperty.create("upgraded"), false);
})
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 2);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(600, 0, (entity) => {
const attachedPlayer = global.cacheOwner(entity, [
"animal_fancy",
"animal_whisperer",
"bff",
"coopmaster",
"heretic",
"mana_hand",
"reaping_scythe",
"shepherd",
]);
global.runAutoGrabber(entity, attachedPlayer);
}),
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)
)
);
}).blockstateJson = {
multipart: []
.concat(getCardinalMultipartJsonBasicUpgradable("auto_grabber", "false"))
.concat(
getCardinalMultipartJsonBasicUpgradable("auto_grabber_upgraded", "true")
),
};
});
@@ -0,0 +1,87 @@
console.info("[SOCIETY] autoPetter.js loaded");
const autoPetterTickRate = 20;
const autoPetterProgTime = 1000;
global.runAutoPetter = (entity) => {
const { block, level } = entity;
let radius = 2;
let dayTime = level.dayTime();
let morningModulo = dayTime % 24000;
if (morningModulo >= autoPetterProgTime && morningModulo < autoPetterProgTime + autoPetterTickRate) {
let day = global.getDay(level);
let nearbyFarmAnimals = level
.getEntitiesWithin(AABB.ofBlock(block).inflate(radius))
.filter((entity) =>
global.checkEntityTag(entity, "society:husbandry_animal")
);
nearbyFarmAnimals.forEach((animal) => {
let data = animal.persistentData;
let ageLastPet = data.getInt("ageLastPet");
let ageLastFed = data.getInt("ageLastFed");
if (day > ageLastPet) {
let hungry = global.compareDay(day, ageLastFed, 1)
let affection = data.getInt("affection");
let affectionIncreaseMult = data.bribed ? 2 : 1;
let affectionIncrease = 5 * affectionIncreaseMult;
if (animal.isBaby()) {
affectionIncrease = affectionIncrease * 2;
}
let livableArea = global.getAnimalIsNotCramped(animal, 1.1);
data.affection = affection + affectionIncrease;
if (hungry || !livableArea) {
data.affection = affection - (hungry ? 15 : 25);
}
data.ageLastPet = day;
level.spawnParticles(
"minecraft:heart",
true,
animal.x,
animal.y + 1.5,
animal.z,
0,
0.1,
0,
1,
0.01
);
}
});
}
};
StartupEvents.registry("block", (e) => {
e.create("society:auto_petter", "cardinal")
.displayName("Auto-Petter")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 0, 16, 8, 16)
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.auto_petter.description").gray()
);
item.tooltip(
Text.translatable("tooltip.society.area", `5x5x5`).green()
);
item.modelJson({
parent: "society:block/kubejs/auto_petter",
});
})
.model("society:block/kubejs/auto_petter")
.blockEntity((blockInfo) => {
blockInfo.serverTick(autoPetterTickRate, 0, (entity) => {
global.runAutoPetter(entity)
})
}).blockstateJson = {
multipart: [
{
apply: { model: "society:block/kubejs/auto_petter_particle" },
},
].concat(getCardinalMultipartJsonBasic("auto_petter")),
};
});
@@ -0,0 +1,60 @@
console.info("[SOCIETY] autoTapper.js loaded");
StartupEvents.registry("block", (event) => {
event
.create("society:auto_tapper", "cardinal")
.displayName("Auto-Tapper")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.property(booleanProperty.create("error"))
.defaultState((state) => {
state.set(booleanProperty.create("error"), false);
})
.placementState((state) => {
state.set(booleanProperty.create("error"), false);
})
.box(0, 0, 0, 16, 18, 16)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.auto_tapper.description").gray());
item.modelJson({
parent: "society:block/kubejs/auto_tapper",
});
})
.blockEntity((blockInfo) => {
blockInfo.initialData({ Fluid: 0, FluidType: "" });
blockInfo.serverTick(200, 0, (entity) => {
global.runAutoTapper(entity);
});
blockInfo.attachCapability(
CapabilityBuilder.FLUID.customBlockEntity()
.getCapacity(() => 10000)
.getFluid((blockInfo, fl) => global.getFluid(blockInfo))
.onFill((blockInfo, fluid, sim) => global.onFill(blockInfo, fluid, sim))
.onDrain((blockInfo, fluid, sim) => global.onDrain(blockInfo, fluid, sim))
);
}).blockstateJson = {
multipart: [
{
apply: { model: "society:block/kubejs/auto_tapper_particle" },
},
{
when: { error: true },
apply: { model: "society:block/kubejs/error" },
},
].concat(getCardinalMultipartJsonBasic("auto_tapper")),
};
});
global.runAutoTapper = (blockInfo) => {
const { block, level } = blockInfo;
const fluidHandler = blockInfo.getCapability(ForgeCapabilities.FLUID_HANDLER).orElse(null);
const fluidData = global.handleTapperRandomTick(
{ block: block, level: level, server: level.getServer() },
true
);
if (global.susFunctionLogging) console.log("[SOCIETY-SUSFN] autoTapper.js");
if (fluidData && block.properties.get("error") == "false") {
fluidHandler.fill(Fluid.of(fluidData.fluid, Math.round(10 / fluidData.time)), "execute");
}
};
@@ -0,0 +1,51 @@
console.info("[SOCIETY] autoWormFarm.js loaded");
StartupEvents.registry("block", (event) => {
event
.create("society:auto_worm_farm")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 0, 16, 16, 16)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.auto_worm_farm.description").gray());
item.tooltip(Text.translatable("society.working_block_entity.can_use_hopper").green());
item.modelJson({
parent: "society:block/kubejs/auto_worm_farm",
});
})
.model("society:block/kubejs/auto_worm_farm")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 1);
blockInfo.serverTick(1200, 0, (entity) => {
const { x, y, z } = entity.block;
if (entity.tick < 20) return;
entity.inventory.insertItem("aquaculture:worm", false);
entity.level.server.runCommandSilent(
`playsound minecraft:block.composter.fill block @a ${x} ${y} ${z}`
);
entity.level.spawnParticles(
"atmospheric:orange_vapor",
true,
x,
y + 0.5,
z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
}),
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.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))
);
});
});
@@ -0,0 +1,90 @@
// priority: 1
console.info("[SOCIETY] basicShippingBin.js loaded");
const debug = false;
const basicCoinMap = [
{ coin: "numismatics:sun", value: 4096 },
{ coin: "numismatics:crown", value: 512 },
{ coin: "numismatics:cog", value: 64 },
{ coin: "numismatics:sprocket", value: 16 },
{ coin: "numismatics:bevel", value: 8 },
{ coin: "numismatics:spur", value: 1 },
];
const calculateSlotsNeeded = (coins) => {
let slots = 0;
coins.forEach((coinObj) => {
let { count } = coinObj;
for (let index = 0; index <= count; index += 64) {
slots++;
}
});
return slots;
};
StartupEvents.registry("block", (event) => {
event
.create("shippingbin:basic_shipping_bin", "cardinal")
.tagBlock("minecraft:mineable/axe")
.item((item) => {
item.tooltip(Text.translatable("tooltip.society.shipping_bin").gray());
item.modelJson({
parent: "shippingbin:block/shipping_bin",
});
})
.model("shippingbin:block/shipping_bin")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 4);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(10, 0, (entity) => {
const { inventory, level, block } = entity;
let dayTime = level.dayTime();
let morningModulo = dayTime % 24000;
if (rnd5()) global.cacheShippingBin(entity);
if (morningModulo >= 5 && morningModulo < 15) {
let slots = inventory.getSlots();
let value = 0;
let binPlayer = global.cacheShippingBin(entity);
let blockData = block.getEntityData().data;
let playerAttributes = blockData.attributes;
let playerStages = blockData.stages;
let removedSlots = [];
let calculationResults;
if (!playerStages || !playerAttributes) return;
calculationResults = global.processShippingBinInventory(
inventory,
slots,
playerAttributes,
playerStages,
true
);
value = Math.round(calculationResults.calculatedValue);
removedSlots = calculationResults.removedItems;
global.processValueOutput(
value,
slots,
removedSlots,
binPlayer,
level.getServer(),
block,
inventory
);
}
}),
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))
);
});
});
@@ -0,0 +1,70 @@
// priority: -21
console.info("[SOCIETY] caterpillarBox.js loaded");
global.handleCaterpillarBox = (e) => {
const { inventory, level, block } = e;
const { x, y, z } = block;
let slots = inventory.getSlots();
let slotItem;
if (!inventory.isEmpty()) {
for (let i = 0; i < slots; i++) {
slotItem = inventory.getStackInSlot(i);
if (slotItem.id == "society:caterpillar_eggs") {
let type = "butterfly";
let longwingDef;
if (slotItem.nbt && slotItem.nbt.child) {
global.longwings.forEach((wing) => {
if (wing.variant === slotItem.nbt.child) {
longwingDef = wing
}
})
type = longwingDef.type;
}
let longwing = level.createEntity("longwings:" + type);
if (longwingDef) {
longwing.mergeNbt({ Variant: longwingDef.variant, size: Math.round(Math.min(global.getLongwingSize(longwingDef.size) * 2, slotItem.nbt.size) * 100) / 100});
}
longwing.setPosition(x, y + 1, z);
longwing.spawn();
slotItem.shrink(1);
return;
}
}
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:caterpillar_box")
.tagBlock("minecraft:mineable/axe")
.soundType("wood")
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.caterpillar_box.description").gray());
item.tooltip(Text.translatable("society.working_block_entity.can_use_hopper").green());
item.modelJson({
parent: "society:block/kubejs/caterpillar_box",
});
})
.model("society:block/kubejs/caterpillar_box")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 1);
blockInfo.serverTick(6000, 0, (entity) => {
global.handleCaterpillarBox(entity);
}),
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.insertItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.insertItem(slot, stack, simulate)
)
.getSlotLimit((blockEntity, slot) =>
blockEntity.inventory.getSlotLimit(slot)
)
.getSlots((blockEntity) => blockEntity.inventory.slots)
.getStackInSlot((blockEntity, slot) =>
blockEntity.inventory.getStackInSlot(slot)
)
);
});
});
@@ -0,0 +1,182 @@
// priority: -21
console.info("[SOCIETY] drumCornucopia.js loaded");
const drumCornucopiaProgTime = 1000;
const fruitTreeBlocks = [
"pamhc2trees:pamorange",
"pamhc2trees:pamdragonfruit",
"pamhc2trees:pampeach",
"pamhc2trees:pamplum",
"pamhc2trees:pambanana",
"pamhc2trees:pamapple",
"pamhc2trees:pamcherry",
"pamhc2trees:pamstarfruit",
"pamhc2trees:pamlychee",
"pamhc2trees:pammango",
"pamhc2trees:pamhazelnut",
"pamhc2trees:pampawpaw",
"pamhc2trees:pamcinnamon",
"pamhc2trees:pampassionfruit",
"pamhc2trees:pamlemon",
];
const dropThree = ["pamhc2trees:pamhazelnut", "pamhc2trees:pamlychee", "pamhc2trees:pambanana"];
const dropModified = ["pamhc2trees:pampassionfruit", "pamhc2trees:pamorange"];
const dropFourModified = ["pamhc2trees:pamcherry", "pamhc2trees:pamapple"];
global.handleCornucopia = (server, level, centerPos, player, returnExperience) => {
let { x, y, z } = centerPos
let scannedBlock;
let fruitDrop;
let fruitType;
let fruitItem;
let fruitCount;
let success = false;
let season;
let modifiedProperties;
let experienceMult = 0;
server.runCommandSilent(
`playsound ${player != null ? "trials:breeze_idle" : "etcetera:block.drum.djembe.low"} block @a ${x} ${y} ${z}`
);
if (!player) {
level.spawnParticles(
"species:ghoul_searching2",
true,
x,
y + 0.5,
z,
0.1 * rnd(0, 1.5),
0.1 * rnd(0, 1.5),
0.1 * rnd(0, 1.5),
1,
0.05
);
}
for (let pos of BlockPos.betweenClosed(new BlockPos(x - 10, y - 2, z - 10), [
x + 10,
y + 10,
z + 10,
])) {
if (!level.isLoaded(pos)) continue;
scannedBlock = level.getBlock(pos);
if (scannedBlock.id == "minecraft:air") continue;
success = false;
fruitDrop = level.createEntity("minecraft:item");
if (["vinery:dark_cherry_leaves", "vinery:apple_leaves"].includes(scannedBlock.id)) {
season = global.getSeasonFromLevel(level);
modifiedProperties = scannedBlock.properties;
if (
season === "spring" &&
scannedBlock.properties.get("has_cherries") &&
scannedBlock.properties.get("has_cherries").toString() === "true"
) {
fruitItem = "vinery:cherry";
fruitItem.count = rnd(0, 4);
success = true;
modifiedProperties.can_grow_cherries = false;
modifiedProperties.has_cherries = false;
scannedBlock.set(scannedBlock.id, modifiedProperties);
} else if (
season === "autumn" &&
scannedBlock.properties.get("has_apples") &&
scannedBlock.properties.get("has_apples").toString() === "true"
) {
fruitItem = "minecraft:apple";
fruitItem.count = rnd(0, 4);
success = true;
modifiedProperties.can_grow_apples = false;
modifiedProperties.has_apples = false;
scannedBlock.set(scannedBlock.id, modifiedProperties);
}
} else if (
fruitTreeBlocks.includes(scannedBlock.id) &&
scannedBlock.properties.get("age") == 7
) {
fruitType = String(scannedBlock.id.split(":")[1]);
fruitCount = 1;
success = true;
if (dropThree.includes(scannedBlock.id)) fruitCount = 3;
if (scannedBlock.id === "pamhc2trees:pambanana") {
if (player && player.stages.has("banana_karenina")) fruitCount *= 2;
else if (Math.random() <= 0.001) scannedBlock.popItem("society:banana_karenina");
}
if (dropModified.includes(scannedBlock.id)) {
fruitItem = Item.of(
scannedBlock.id === "pamhc2trees:pampassionfruit"
? "atmospheric:passion_fruit"
: "atmospheric:orange"
);
} else if (dropFourModified.includes(scannedBlock.id)) {
fruitCount = 4;
fruitItem = Item.of(
scannedBlock.id === "pamhc2trees:pamcherry" ? "vinery:cherry" : "minecraft:apple"
);
} else {
fruitItem = Item.of(`pamhc2trees:${fruitType.substring(3, fruitType.length)}item`);
}
fruitItem.count = player && player.stages.has("tree_whisperer") ? fruitCount + 2 : fruitCount;
scannedBlock.set(scannedBlock.id, {
waterlogged: scannedBlock.properties.get("waterlogged") || "false",
age: "0",
});
}
if (success) {
fruitDrop.x = scannedBlock.x;
fruitDrop.y = scannedBlock.y;
fruitDrop.z = scannedBlock.z;
fruitDrop.item = fruitItem;
fruitDrop.spawn();
experienceMult++;
level.spawnParticles(
"mysticaloaktree:wind",
true,
scannedBlock.x,
scannedBlock.y + 0.5,
scannedBlock.z,
0.1 * rnd(0, 1.5),
0.1 * rnd(0, 1.5),
0.1 * rnd(0, 1.5),
7,
0.05
);
server.runCommandSilent(
`playsound minecraft:block.grass.break block @a ${scannedBlock.x} ${scannedBlock.y} ${scannedBlock.z} 0.5`
);
}
}
if (returnExperience) return experienceMult;
};
StartupEvents.registry("block", (event) => {
event
.create("society:drum_cornucopia")
.displayName("Drum of the Cornucopia")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.soundType("wood")
.defaultCutout()
.model("society:block/kubejs/drum_cornucopia")
.box(3, 0, 3, 13, 14, 13)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.drum_cornucopia.description").gray());
item.tooltip(Text.translatable("tooltip.society.area", `20x10x20`).green());
item.modelJson({
parent: "society:block/kubejs/drum_cornucopia",
});
})
.blockEntity((blockInfo) => {
blockInfo.serverTick(artMachineTickRate, 0, (e) => {
const { level, block } = e;
let dayTime = level.dayTime();
let morningModulo = dayTime % 24000;
if (
morningModulo >= drumCornucopiaProgTime &&
morningModulo < drumCornucopiaProgTime + artMachineTickRate
) {
global.handleCornucopia(level.server, level, block.getPos())
}
})
})
});
@@ -0,0 +1,293 @@
console.info("[SOCIETY] feedingTrough.js loaded");
const feedFunction = (
level,
animal,
day,
inventory,
hasAnimalFeed,
hasCandiedFeed,
hasManaFeed
) => {
let data = animal.persistentData;
if (!data.getInt("ageLastFed") || day < data.getInt("ageLastFed")) {
data.ageLastFed = day;
}
if (day > data.ageLastFed) {
let fed = false;
let boost = 0;
// prefer candied > mana > normal
if (
hasCandiedFeed &&
global.useInventoryItems(inventory, "society:candied_animal_feed", 1) == 1
) {
fed = true;
boost = 100;
} else if (hasManaFeed && global.useInventoryItems(inventory, "society:mana_feed", 1) == 1) {
fed = true;
boost = 30;
} else if (
hasAnimalFeed &&
global.useInventoryItems(inventory, "society:animal_feed", 1) == 1
) {
fed = true;
}
if (fed) {
animal.heal(4);
data.ageLastFed = day;
if (boost > 0) data.affection = data.getInt("affection") + boost;
level.spawnParticles(
"legendarycreatures:wisp_particle",
true,
animal.x,
animal.y + 1.5,
animal.z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
}
}
};
global.runFeedingTrough = (be, inventory, block, level) => {
let radius = 6;
let hasAnimalFeed = global.inventoryHasItems(inventory, "society:animal_feed", 1) == 1;
let hasCandiedFeed = global.inventoryHasItems(inventory, "society:candied_animal_feed", 1) == 1;
let hasManaFeed = global.inventoryHasItems(inventory, "society:mana_feed", 1) == 1;
if (!(hasAnimalFeed || hasCandiedFeed || hasManaFeed)) return;
let slots = inventory.getSlots();
let feedCount = 0;
let nearbyFarmAnimals;
let day = global.getDay(level);
nearbyFarmAnimals = level
.getEntitiesWithin(AABB.ofBlock(block).inflate(radius))
.filter((entity) => global.checkEntityTag(entity, "society:husbandry_animal"));
nearbyFarmAnimals.forEach((animal) => {
feedFunction(level, animal, day, inventory, hasAnimalFeed, hasCandiedFeed, hasManaFeed);
});
// Handle visual
for (let i = 0; i < slots; i++) {
if (inventory.getStackInSlot(i).hasTag("society:animal_feed"))
feedCount += inventory.getStackInSlot(i).count;
}
let fill = 0;
if (feedCount >= 512) fill = 4;
else if (feedCount >= 256) fill = 3;
else if (feedCount >= 128) fill = 2;
else if (feedCount >= 8) fill = 1;
be.block.set(be.block.id, {
facing: be.block.properties.facing,
fill: String(fill),
});
};
StartupEvents.registry("block", (event) => {
event
.create("society:feeding_trough", "cardinal")
.property(integerProperty.create("fill", 0, 4))
.tagBlock("minecraft:mineable/axe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 2, 16, 12, 14)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.feeding_trough.description").gray());
item.tooltip(Text.translatable("tooltip.society.area", `13x13x13`).green());
item.modelJson({
parent: "farm_and_charm:block/feeding_trough_size_0",
});
})
.defaultState((state) => {
state.set(integerProperty.create("fill", 0, 4), 0);
})
.placementState((state) => {
state.set(integerProperty.create("fill", 0, 4), 0);
})
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 1);
blockInfo.initialData({ fill: "0" });
blockInfo.serverTick(300, 0, (entity) => {
const { inventory, block, level } = entity;
global.runFeedingTrough(entity, inventory, block, level);
}),
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))
);
}).blockstateJson = {
multipart: [
{
when: { fill: 0, facing: "north" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_0",
y: 0,
uvlock: false,
},
},
{
when: { fill: 0, facing: "east" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_0",
y: 90,
uvlock: false,
},
},
{
when: { fill: 0, facing: "south" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_0",
y: 180,
uvlock: false,
},
},
{
when: { fill: 0, facing: "west" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_0",
y: -90,
uvlock: false,
},
},
{
when: { fill: 1, facing: "north" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_1",
y: 0,
uvlock: false,
},
},
{
when: { fill: 1, facing: "east" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_1",
y: 90,
uvlock: false,
},
},
{
when: { fill: 1, facing: "south" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_1",
y: 180,
uvlock: false,
},
},
{
when: { fill: 1, facing: "west" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_1",
y: -90,
uvlock: false,
},
},
{
when: { fill: 2, facing: "north" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_2",
y: 0,
uvlock: false,
},
},
{
when: { fill: 2, facing: "east" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_2",
y: 90,
uvlock: false,
},
},
{
when: { fill: 2, facing: "south" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_2",
y: 180,
uvlock: false,
},
},
{
when: { fill: 2, facing: "west" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_2",
y: -90,
uvlock: false,
},
},
{
when: { fill: 3, facing: "north" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_3",
y: 0,
uvlock: false,
},
},
{
when: { fill: 3, facing: "east" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_3",
y: 90,
uvlock: false,
},
},
{
when: { fill: 3, facing: "south" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_3",
y: 180,
uvlock: false,
},
},
{
when: { fill: 3, facing: "west" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_3",
y: -90,
uvlock: false,
},
},
{
when: { fill: 4, facing: "north" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_4",
y: 0,
uvlock: false,
},
},
{
when: { fill: 4, facing: "east" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_4",
y: 90,
uvlock: false,
},
},
{
when: { fill: 4, facing: "south" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_4",
y: 180,
uvlock: false,
},
},
{
when: { fill: 4, facing: "west" },
apply: {
model: "farm_and_charm:block/feeding_trough_size_4",
y: -90,
uvlock: false,
},
},
],
};
});
@@ -0,0 +1,274 @@
console.info("[SOCIETY] artisanHopper.js loaded");
/**
* @param {Internal.BlockEntityJS} fishPondBasket
* @param {Internal.Player|null} player
*/
global.runFishPondBasket = (fishPondBasket, fishPondPos, player) => {
const { level, block, inventory } = fishPondBasket;
const stages = global.getBlockEntityStages(fishPondBasket);
const server = level.server;
const fishPond = level.getBlock(fishPondPos);
const { x, y, z } = fishPond;
let machineOutputs;
let newProperties = fishPond.getProperties();
let nbt = fishPond.getEntityData();
let recycleSparkstone;
const { type, max_population, population } = nbt.data;
if (global.inventoryHasItems(inventory, "society:sparkstone", 1) != 1) return;
recycleSparkstone = global.checkSparkstoneRecyclers(level, block);
if (
newProperties.get("mature").toLowerCase() === "true" &&
global.inventoryBelowHasRoom(level, block, global.getRoe(type)) &&
(recycleSparkstone || global.useInventoryItems(inventory, "society:sparkstone", 1) == 1)
) {
machineOutputs = global.handleFishHarvest(fishPond, player, server, true, stages);
if (machineOutputs.length > 0) {
machineOutputs.forEach((item) => {
global.insertBelow(level, block, item);
});
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
);
}
}
if (
newProperties.get("mature").toLowerCase() === "true" &&
level.getBlock(block.pos).getProperties().get("upgraded") === "true" &&
population > 0 && max_population === population
) {
let fishie = global.handleFishExtraction(fishPond, player, server, stages);
recycleSparkstone = global.checkSparkstoneRecyclers(level, block);
if (
global.inventoryBelowHasRoom(level, block, fishie) &&
(recycleSparkstone || global.useInventoryItems(inventory, "society:sparkstone", 1) == 1)
) {
global.insertBelow(level, block, fishie);
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
);
}
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:fish_pond_basket")
.tagBlock("minecraft:mineable/axe")
.tagBlock("minecraft:needs_stone_tool")
.waterlogged()
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.fish_pond_basket.description").gray()
);
item.tooltip(
Text.translatable(
"society.working_block_entity.apply_player_skill"
).gray()
);
item.tooltip(
Text.translatable(
"block.society.fish_pond_basket.description.upgrade"
).gold()
);
item.tooltip(Text.translatable("tooltip.society.area", `3x3x3`).green());
item.tooltip(
Text.translatable(
"block.society.fish_pond_basket.description.fuel"
).lightPurple()
);
item.modelJson({
parent: "society:block/kubejs/fish_pond_basket",
});
item.fireResistant(true);
})
.soundType("copper")
.model("society:block/kubejs/fish_pond_basket")
.property(booleanProperty.create("upgraded"))
.defaultState((state) => {
state
.set(booleanProperty.create("upgraded"), false)
.set(BlockProperties.WATERLOGGED, false);
})
.placementState((state) => {
state
.set(booleanProperty.create("upgraded"), false)
.set(BlockProperties.WATERLOGGED, false);
})
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 2);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(600, 0, (entity) => {
const { block, level } = entity;
const { x, y, z } = block;
const radius = 1;
let attachedPlayer = global.cacheOwner(entity, [
"bullfish_jobs",
"caper_catcher",
"caviar_catcher",
"hot_hands",
"mitosis",
"scum_collector",
]);
let scanBlock;
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.id === "society:fish_pond") {
global.runFishPondBasket(entity, pos.immutable(), attachedPlayer);
}
}
}),
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)
)
);
}).blockstateJson = {
multipart: [
{
when: { upgraded: "false" },
apply: { model: "society:block/kubejs/fish_pond_basket" },
},
{
when: { upgraded: "true" },
apply: { model: "society:block/kubejs/fish_pond_basket_upgraded" },
},
],
};
event
.create("society:fish_pond_hatchery")
.tagBlock("minecraft:mineable/axe")
.tagBlock("minecraft:needs_stone_tool")
.waterlogged()
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.fish_pond_basket.description").gray()
);
item.tooltip(
Text.translatable(
"society.working_block_entity.apply_player_skill"
).gray()
);
item.tooltip(
Text.translatable(
"block.society.fish_pond_basket.description.upgrade"
).gold()
);
item.tooltip(Text.translatable("tooltip.society.area", `3x7x3`).green());
item.tooltip(
Text.translatable(
"block.society.fish_pond_basket.description.fuel"
).lightPurple()
);
item.modelJson({
parent: "society:block/kubejs/fish_pond_hatchery",
});
item.fireResistant(true);
})
.soundType("copper")
.model("society:block/kubejs/fish_pond_hatchery")
.property(booleanProperty.create("upgraded"))
.defaultState((state) => {
state
.set(booleanProperty.create("upgraded"), false)
.set(BlockProperties.WATERLOGGED, false);
})
.placementState((state) => {
state
.set(booleanProperty.create("upgraded"), false)
.set(BlockProperties.WATERLOGGED, false);
})
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 2);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(600, 0, (entity) => {
const { block, level } = entity;
const { x, y, z } = block;
let attachedPlayer = global.cacheOwner(entity, [
"bullfish_jobs",
"caper_catcher",
"caviar_catcher",
"hot_hands",
"mitosis",
"scum_collector",
]);
let scanBlock;
for (let pos of BlockPos.betweenClosed(
new BlockPos(x - 1, y - 3, z - 1),
[x + 1, y + 3, z + 1]
)) {
if (!level.isLoaded(pos)) continue;
scanBlock = level.getBlock(pos);
if (scanBlock.id === "society:fish_pond") {
global.runFishPondBasket(entity, pos.immutable(), attachedPlayer);
}
}
}),
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)
)
);
}).blockstateJson = {
multipart: [
{
when: { upgraded: "false" },
apply: { model: "society:block/kubejs/fish_pond_hatchery" },
},
{
when: { upgraded: "true" },
apply: { model: "society:block/kubejs/fish_pond_hatchery_upgraded" },
},
],
};
});
@@ -0,0 +1,229 @@
//priority: 100
console.info("[SOCIETY] fishPondQuestManager.js loaded");
global.handleManagerQuestSubmission = (entity, fishPondPos, attachedPlayer, delay) => {
const { level, block, inventory } = entity;
const server = level.server;
server.scheduleInTicks(delay, () => {
const fishPond = level.getBlock(fishPondPos);
const { x, y, z } = fishPond;
const nbt = fishPond.getEntityData();
if (!nbt || !nbt.data) {
return;
}
const { type: fishType, max_population, quest_id } = nbt.data;
const { facing, valid, mature, upgraded, quest } =
global.getPondProperties(fishPond);
if (quest === "true" && global.fishPondDefinitions.get(`${fishType}`)) {
const questContent = getRequestedItems(fishType, Number(max_population))[quest_id];
if (!questContent) {
return;
}
let checkedCount = attachedPlayer.stages.has("pond_house_five") ?
Math.round(questContent.count / 2) :
questContent.count;
if (global.hasInventoryItems(inventory, questContent.item, checkedCount)) {
successParticles(level, fishPond);
fishPond.set(fishPond.id, {
facing: facing,
valid: valid,
mature: mature,
upgraded: upgraded,
quest: false,
});
nbt.merge({
data: {
quest_id: 0,
max_population: increaseStage(max_population, Number(max_population) === 7 ? 3 : 2),
},
});
fishPond.setEntityData(nbt);
global.inventoryUseItems(inventory, questContent.item, checkedCount);
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
);
}
}
});
}
global.getQuestItems = (block, level) => {
let requestedItems = [];
const { x, y, z } = block;
let attachedPlayer;
const ownerUuid = block.getEntityData().data.owner;
if (ownerUuid === "-1") return;
for (const p of level.getServer().players) {
if (p.getUuid().toString() === ownerUuid) {
attachedPlayer = p;
break;
}
}
if (attachedPlayer) {
let radius = 10;
let scanBlock;
let halfCost = attachedPlayer.stages.has("pond_house_five");
for (let pos of BlockPos.betweenClosed(new BlockPos(x - radius, y - radius, z - radius),
[x + radius, y + radius, z + radius])) {
scanBlock = level.getBlock(pos);
if (scanBlock.id === "society:fish_pond") {
let nbt = scanBlock.getEntityData();
if (!nbt || !nbt.data) continue;
let { type: fishType, max_population, quest_id } = nbt.data;
let { quest } = global.getPondProperties(scanBlock);
if (quest === "true" && global.fishPondDefinitions.get(`${fishType}`)) {
let questContent = getRequestedItems(fishType, Number(max_population))[quest_id];
if (!questContent) {
continue;
}
let checkedCount = halfCost ?
Math.round(questContent.count / 2) :
questContent.count;
let requestedItem = questContent.item;
requestedItems.push({ item: requestedItem, count: checkedCount });
}
}
}
}
const groupedMap = new Map();
for (let i = 0; i < requestedItems.length; i++) {
let entry = requestedItems[i];
groupedMap.set(entry.item, (groupedMap.get(entry.item) || 0) + entry.count);
}
const entries = [];
groupedMap.forEach(function (count, item) {
const displayName = Item.of(item).displayName.string;
entries.push({
Checked: "0b",
Text: `{"text":"${count} x ${displayName}"}`,
});
});
const pageSize = 6;
let pages = [];
for (let i = 0; i < entries.length; i += pageSize) {
pages.push({ Entries: entries.slice(i, i + pageSize) });
}
return pages;
}
global.runFishPondQuestManager = (entity) => {
const { block, level } = entity;
const { x, y, z } = block;
let attachedPlayer;
const cDayTime = level.dayTime();
const currentMorningModulo = cDayTime % 24000;
const questManagerProgTime = 1000;
if (currentMorningModulo < questManagerProgTime ||
currentMorningModulo >= questManagerProgTime + artMachineTickRate) return;
const ownerUuid = block.getEntityData().data.owner;
if (ownerUuid === "-1") return;
for (const p of level.getServer().players) {
if (p.getUuid().toString() === ownerUuid) {
attachedPlayer = p;
break;
}
}
if (attachedPlayer) {
const radius = 10;
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])) {
scanBlock = level.getBlock(pos);
if (scanBlock.id === "society:fish_pond") {
global.handleManagerQuestSubmission(
entity,
pos.immutable(),
attachedPlayer,
scannedBlocks * 5);
scannedBlocks++;
}
}
level.server.runCommandSilent(
`playsound botania:spreader_fire block @a ${x} ${y} ${z}`
)
}
}
StartupEvents.registry("block", (event) => {
event
.create("society:fish_pond_manager", "cardinal")
.tagBlock("minecraft:mineable/axe")
.tagBlock("minecraft:needs_stone_tool")
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.fish_pond_manager.description").gray());
item.tooltip(Text.translatable("society.working_block_entity.apply_player_skill").gray());
item.tooltip(Text.translatable("tooltip.society.area", `21x21x21`).green());
item.modelJson({
parent: "society:block/kubejs/fish_pond_manager",
});
})
.soundType("copper")
.model("society:block/kubejs/fish_pond_manager")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 2);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(artMachineTickRate, 0, (entity) => {
global.runFishPondQuestManager(entity);
});
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)
)
);
});
});
@@ -0,0 +1,73 @@
console.info("[SOCIETY] growthObelisk.js loaded");
const RandomSource = Java.loadClass("net.minecraft.util.RandomSource");
const growthObeliskProgTime = 1000;
global.runGrowthObelisk = (tickEvent) => {
const { level, block, inventory } = tickEvent;
const { x, y, z } = block;
const server = level.server;
let dayTime = level.dayTime();
let morningModulo = dayTime % 24000;
level.spawnParticles("snowyspirit:glow_light", true, x + 0.5, y + 2.2, z + 0.5, 0, 0, 0, 2, 2);
if (
morningModulo >= growthObeliskProgTime &&
morningModulo < growthObeliskProgTime + artMachineTickRate
) {
if (global.hasInventoryItems(inventory, "society:spark_gro", 1)) {
global.useInventoryItems(inventory, "society:spark_gro", 1);
level.spawnParticles("species:ghoul_searching", true, x + 0.5, y, z + 0.5, 0, 0, 0, 1, 2);
server.runCommandSilent(`playsound ribbits:entity.ribbit.magic block @a ${x} ${y} ${z} 1`);
server.scheduleInTicks(4, () => {
CropGrowthUtils.growCropsInRadius(level, block.getPos(), RandomSource.create(), 4);
});
}
}
};
StartupEvents.registry("block", (e) => {
e
.create("society:growth_obelisk", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.growth_obelisk.description").gray());
item.tooltip(Text.translatable("tooltip.society.area", `7x1x7`).green());
item.tooltip(Text.translatable("block.society.growth_obelisk.description.fuel").lightPurple());
item.modelJson({
parent: "society:block/kubejs/growth_obelisk/display",
});
})
.soundType("stone")
.model("society:block/kubejs/growth_obelisk/lower")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 2);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(artMachineTickRate, 0, (entity) => {
global.runGrowthObelisk(entity, 4);
}),
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))
);
});
e
.create("society:growth_obelisk_upper", "cardinal")
.box(4, 0, 4, 12, 9, 12)
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.defaultCutout()
.soundType("stone")
.model("society:block/kubejs/growth_obelisk/upper");
});
@@ -0,0 +1,77 @@
console.info("[SOCIETY] juiceInserter.js loaded");
StartupEvents.registry("block", (event) => {
event
.create("society:juice_inserter", "cardinal")
.tagBlock("minecraft:mineable/axe")
.box(1, 0, 1, 15, 16, 15)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.juice_inserter.description").gray());
item.modelJson({
parent: "society:block/kubejs/juice_inserter",
});
})
.blockEntity((blockInfo) => {
blockInfo.initialData({ Fluid: 0, FluidType: "" });
blockInfo.serverTick(10, 0, (entity) => {
global.runJuiceInserter(entity);
});
blockInfo.attachCapability(
CapabilityBuilder.FLUID.customBlockEntity()
.getCapacity(() => 10000)
.getFluid((blockInfo, fl) => global.getFluid(blockInfo))
.onFill((blockInfo, fluid, sim) => global.onFill(blockInfo, fluid, sim))
.onDrain((blockInfo, fluid, sim) => global.onDrain(blockInfo, fluid, sim))
);
}).blockstateJson = {
multipart: [
{
apply: { model: "society:block/kubejs/juice_inserter_particle" },
},
].concat(getCardinalMultipartJsonBasic("juice_inserter")),
};
});
const juiceMap = [
{ fluid: "vinery:white_grape_juice", barrelFluidId: "white_general" },
{ fluid: "vinery:white_savanna_grape_juice", barrelFluidId: "white_savanna" },
{ fluid: "vinery:white_taiga_grape_juice", barrelFluidId: "white_taiga" },
{ fluid: "vinery:white_jungle_grape_juice", barrelFluidId: "white_jungle" },
{ fluid: "nethervinery:warped_grape_juice", barrelFluidId: "white_warped" },
{ fluid: "vinery:red_grape_juice", barrelFluidId: "red_general" },
{ fluid: "vinery:red_savanna_grape_juice", barrelFluidId: "red_savanna" },
{ fluid: "vinery:red_taiga_grape_juice", barrelFluidId: "red_taiga" },
{ fluid: "vinery:red_jungle_grape_juice", barrelFluidId: "red_jungle" },
{ fluid: "nethervinery:crimson_grape_juice", barrelFluidId: "red_crimson" },
{ fluid: "vinery:apple_juice", barrelFluidId: "apple" },
];
global.runJuiceInserter = (blockInfo) => {
const { block, level } = blockInfo;
const fluidHandler = blockInfo.getCapability(ForgeCapabilities.FLUID_HANDLER).orElse(null);
const fermentationBarrel = global.getFermentingBarrel(level, level.getBlock(block.getPos()));
if (!fermentationBarrel.id.equals("vinery:fermentation_barrel")) return;
let barrelData = fermentationBarrel.getEntityData();
if (!barrelData) return;
if (!block.getEntityData()) return;
const fluidData = block.getEntityData().ForgeData;
if (!barrelData) return;
if (Number(barrelData.FluidLevel) + 25 > 100) return;
if (fluidData === null || fluidData.Fluid < 250) return;
juiceMap.forEach((juice) => {
if (fluidData.FluidType && fluidData.FluidType.equals(juice.fluid)) {
if (barrelData.FluidLevel === 0) {
barrelData.JuiceType = juice.barrelFluidId;
fermentationBarrel.setEntityData(barrelData);
}
if (barrelData.JuiceType.equals(juice.barrelFluidId)) {
fluidHandler.drain(Fluid.of(fluidData.FluidType, 250), "execute");
barrelData.FluidLevel = barrelData.FluidLevel + 25.0;
fermentationBarrel.setEntityData(barrelData);
level
.getServer()
.runCommandSilent(`playsound create:spout block @a ${block.x} ${block.y} ${block.z}`);
}
}
});
};
@@ -0,0 +1,150 @@
console.info("[SOCIETY] manaFruit.js loaded");
const MANA_DRAIN = 2500;
const FRUIT_MAX_MANA = MANA_DRAIN * 4;
global.handleManaFruit = (e) => {
const { level, block } = e;
const { x, y, z } = block;
let dayTime = level.dayTime();
let morningModulo = dayTime % 24000;
let blockProperties = level.getBlock(block.pos).getProperties();
let age = Number(blockProperties.get("age"));
if (!global.surviveCheck(level, block.pos))
level.destroyBlock(block.pos, true);
if (age < 7 && morningModulo >= 20 && morningModulo < 40) {
let mana = e.persistentData.getInt("mana");
if (mana >= MANA_DRAIN) {
blockProperties.age = String(
age +
CropGrowthUtils.getFertilizerIncrease(
age,
7,
level.getBlockState(block.pos.below())
)
);
block.set(block.id, blockProperties);
e.persistentData.putInt("mana", mana - MANA_DRAIN);
level.server.runCommandSilent(
`playsound botania:mana_pool_craft block @a ${x} ${y} ${z}`
);
level.spawnParticles(
"windswept:will_o_the_wisp",
true,
x,
y + 0.25,
z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
} else if (age > 0) {
blockProperties.age = String(age - 1);
block.set(block.id, blockProperties);
level.server.runCommandSilent(
`playsound botania:virus_infect block @a ${x} ${y} ${z}`
);
level.spawnParticles(
"farmlife:stinky",
true,
x,
y + 0.25,
z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
}
}
};
StartupEvents.registry("block", (e) => {
e
.create("society:mana_fruit_crop")
.defaultCutout()
.hardness(0)
.resistance(0)
.displayName("Mana Fruit Seed")
.mapColor("grass")
.soundType("azalea_leaves")
.box(1, 0, 1, 15, 4, 15)
.property(integerProperty.create("age", 0, 7))
.defaultState((state) => {
state.set(integerProperty.create("age", 0, 7), 0);
})
.placementState((state) => {
state.set(integerProperty.create("age", 0, 7), 0);
})
.tagBlock("minecraft:mineable/hoe")
.tagBlock("minecraft:crops")
.blockEntity((blockInfo) => {
blockInfo.serverTick(20, 0, (entity) => global.handleManaFruit(entity)),
blockInfo.attachCapability(
BotaniaCapabilityBuilder.MANA.blockEntity()
.canReceiveManaFromBurst((be) => {
let mana = be.persistentData.getInt("mana");
return mana < FRUIT_MAX_MANA;
})
.receiveMana((be, amount) => {
let currentMana = be.persistentData.getInt("mana");
let received = Math.min(FRUIT_MAX_MANA - currentMana, amount);
be.persistentData.putInt("mana", currentMana + received);
})
.getCurrentMana((be) => be.persistentData.getInt("mana"))
.isFull((be) => {
let mana = be.persistentData.getInt("mana");
return mana >= FRUIT_MAX_MANA;
})
);
})
.item((item) => {
item.tooltip(
Text.translatable("society.working_block_entity.need_mana").aqua()
);
item.modelJson({
parent: "minecraft:item/generated",
textures: {
layer0: "society:item/mana_fruit_seed",
},
});
}).blockstateJson = {
multipart: [
{
when: { age: 0 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage0" },
},
{
when: { age: 1 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage1" },
},
{
when: { age: 2 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage1" },
},
{
when: { age: 3 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage2" },
},
{
when: { age: 4 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage2" },
},
{
when: { age: 5 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage3" },
},
{
when: { age: 6 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage4" },
},
{
when: { age: 7 },
apply: { model: "society:block/kubejs/crops/mana_fruit_crop_stage5" },
},
],
};
});
@@ -0,0 +1,110 @@
console.info("[SOCIETY] manaMilker.js loaded");
const MANA_PER_MILK = 400;
const MAX_MANA = MANA_PER_MILK * 10;
StartupEvents.registry("block", (event) => {
event
.create("society:mana_milker")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 0, 16, 16, 16)
.defaultCutout()
.soundType("copper")
.item((item) => {
item.tooltip(
Text.translatable("block.society.mana_milker.description").gray()
);
item.tooltip(
Text.translatable("society.working_block_entity.can_use_hopper").green()
);
item.tooltip(
Text.translatable("society.working_block_entity.need_mana").aqua()
);
item.tooltip(
Text.translatable("tooltip.society.area", `10x10x10`).green()
);
item.modelJson({
parent: "society:block/kubejs/mana_milker",
});
})
.model("society:block/kubejs/mana_milker")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 1);
blockInfo.serverTick(1200, 0, (entity) => {
const { inventory, block, level } = entity;
let mana = entity.persistentData.getInt("mana");
inventory.allItems;
let nearbyFarmAnimals;
nearbyFarmAnimals = level
.getEntitiesWithin(AABB.ofBlock(block).inflate(10))
.filter((entity) =>
global.checkEntityTag(entity, "society:milkable_animal")
);
nearbyFarmAnimals.forEach((animal) => {
let data = animal.persistentData;
if (mana >= MANA_PER_MILK) {
const day = global.getDay(level);
let milkItem = global.getMilk(
level, animal, data, null, day, undefined, undefined, global.NO_STAGES
);
if (milkItem !== -1) {
let success = entity.inventory.insertItem(milkItem, false);
if (success) {
entity.persistentData.putInt("mana", mana - MANA_PER_MILK);
level.server.runCommandSilent(
`playsound minecraft:entity.cow.milk block @a ${animal.x} ${animal.y} ${animal.z}`
);
level.spawnParticles(
"atmospheric:aloe_blossom",
true,
animal.x,
animal.y + 1.5,
animal.z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
5,
0.01
);
}
}
}
});
}),
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)
)
);
blockInfo.attachCapability(
BotaniaCapabilityBuilder.MANA.blockEntity()
.canReceiveManaFromBurst((be) => {
let mana = be.persistentData.getInt("mana");
return mana < MAX_MANA;
})
.receiveMana((be, amount) => {
let currentMana = be.persistentData.getInt("mana");
let received = Math.min(MAX_MANA - currentMana, amount);
be.persistentData.putInt("mana", currentMana + received);
})
.getCurrentMana((be) => be.persistentData.getInt("mana"))
.isFull((be) => {
let mana = be.persistentData.getInt("mana");
return mana >= MAX_MANA;
})
);
});
});
@@ -0,0 +1,98 @@
console.info("[SOCIETY] manaSprinkler.js loaded");
const MANA_PER_SPRINKLE = 50;
const SPRINKLER_MAX_MANA = MANA_PER_SPRINKLE * 25 * 8;
global.manaSprinklerScan = (entity, radius) => {
const { block, level } = entity;
const { x, y, z } = block;
let scanBlock;
let sprinklerMana = entity.persistentData.getInt("mana");
let flowerBE
let triggeredSpread = false;
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.id == "society:mana_fruit_crop") {
sprinklerMana = entity.persistentData.getInt("mana");
flowerBE = scanBlock.entity
if (sprinklerMana > MANA_PER_SPRINKLE && flowerBE.persistentData.getInt("mana") < FRUIT_MAX_MANA) {
flowerBE.persistentData.putInt("mana", flowerBE.persistentData.getInt("mana") + MANA_PER_SPRINKLE);
entity.persistentData.putInt("mana", entity.persistentData.getInt("mana") - MANA_PER_SPRINKLE);
flowerBE.setChanged()
entity.setChanged()
triggeredSpread = true;
level.spawnParticles(
"windswept:will_o_the_wisp",
true,
scanBlock.x + 0.5,
scanBlock.y + 1.25,
scanBlock.z + 0.5,
0, 0, 0,
1,
0.01
);
}
}
}
if (triggeredSpread) {
level.server.runCommandSilent(
`playsound doapi:water_sprinkler block @a ${x} ${y} ${z} 0.5 1`
);
level.server.runCommandSilent(
`playsound botania:spreader_fire block @a ${x} ${y} ${z} 0.5 1`
);
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:mana_sprinkler")
.tagBlock("minecraft:mineable/axe")
.tagBlock("minecraft:needs_stone_tool")
.tagBlock("dew_drop_farmland_growth:sprinkler_tier_2")
.defaultCutout()
.soundType("wood")
.item((item) => {
item.tooltip(
Text.translatable("block.society.mana_sprinkler.description").aqua()
);
item.tooltip(Text.translatable(
"tooltip.society.area",
`5x5`
).green())
item.tooltip(
Text.translatable("block.society.mana_sprinkler.need_mana").aqua()
);
item.modelJson({
parent: "society:block/kubejs/mana_sprinkler",
});
})
.model("society:block/kubejs/mana_sprinkler")
.blockEntity((blockInfo) => {
blockInfo.serverTick(20, 0, (entity) => {
global.manaSprinklerScan(entity, 2);
}),
blockInfo.attachCapability(
BotaniaCapabilityBuilder.MANA.blockEntity()
.canReceiveManaFromBurst((be) => {
let mana = be.persistentData.getInt("mana");
return mana < SPRINKLER_MAX_MANA;
})
.receiveMana((be, amount) => {
let currentMana = be.persistentData.getInt("mana");
let received = Math.min(SPRINKLER_MAX_MANA - currentMana, amount);
be.persistentData.putInt("mana", currentMana + received);
})
.getCurrentMana((be) => be.persistentData.getInt("mana"))
.isFull((be) => {
let mana = be.persistentData.getInt("mana");
return mana >= SPRINKLER_MAX_MANA;
})
);
});
});
@@ -0,0 +1,113 @@
// priority: -21
console.info("[SOCIETY] picklingCan.js loaded");
global.picklingRecipes = new Map([
["vintagedelight:ghost_pepper", { pickle: "vintagedelight:pickled_pepper" }],
["vintagedelight:cucumber", { pickle: "vintagedelight:pickle" }],
["minecraft:pitcher_pod", { pickle: "vintagedelight:pickled_pitcher_pod" }],
["minecraft:beetroot", { pickle: "vintagedelight:pickled_beetroot" }],
["farm_and_charm:onion", { pickle: "vintagedelight:pickled_onion" }],
["farmersdelight:cabbage", { pickle: "vintagedelight:kimchi" }],
["farmersdelight:cabbage_leaf", { pickle: "vintagedelight:kimchi" }],
["minecraft:egg", { pickle: "vintagedelight:pickled_egg" }],
["minecraft:turtle_egg", { pickle: "vintagedelight:pickled_egg" }],
["untitledduckmod:duck_egg", { pickle: "vintagedelight:pickled_egg" }],
["untitledduckmod:goose_egg", { pickle: "vintagedelight:pickled_egg" }],
["autumnity:turkey_egg", { pickle: "vintagedelight:pickled_egg" }],
["farmlife:galliraptor_egg", { pickle: "vintagedelight:pickled_egg" }],
["society:penguin_egg", { pickle: "vintagedelight:pickled_egg" }],
["society:flamingo_egg", { pickle: "vintagedelight:pickled_egg" }],
["society:cracked_egg", { pickle: "vintagedelight:pickled_egg" }],
]);
global.picklableVegetables.forEach((pickle) => {
global.picklingRecipes.set(pickle.item, {
pickle: `society:pickled_${pickle.item.split(":")[1]}`,
});
});
global.handlePicklingCan = (e) => {
const { inventory, level, block } = e;
const { x, y, z } = block;
let radius = 1;
let slots = inventory.getSlots();
let slotItem;
const belowPos = block.getPos().below();
const belowBlock = level.getBlock(belowPos.x, belowPos.y, belowPos.z);
if (belowBlock.inventory && !inventory.isEmpty()) {
for (let i = 0; i < slots; i++) {
slotItem = inventory.getStackInSlot(i);
if (
slotItem !== Item.of("minecraft:air") &&
global.picklingRecipes.get(`${slotItem.id}`)
) {
let pickle = global.picklingRecipes.get(`${slotItem.id}`).pickle;
let pickleItem = Item.of(`1x ${pickle}`, slotItem.nbt);
if (global.inventoryBelowHasRoom(level, block, pickleItem)) {
let scanBlock;
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.id === "vintagedelight:salt") {
let saltProperties = scanBlock.getProperties();
if (rnd50()) {
if (Number(saltProperties.get("layers")) > 1) {
saltProperties.layers = `${Number(saltProperties.get("layers")) - 1
}`;
scanBlock.set(scanBlock.id, saltProperties);
} else {
scanBlock.set("minecraft:air");
}
}
global.insertBelow(level, block, pickleItem);
slotItem.count--;
return;
}
}
}
}
}
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:pickling_can")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.soundType("copper")
.box(1, 0, 1, 15, 15, 15)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.prickly_can.description").gray());
item.tooltip(Text.translatable("block.society.prickly_can.description.warn").red());
item.tooltip(Text.translatable("society.working_block_entity.can_use_hopper").green());
item.tooltip(Text.translatable("society.working_block_entity.preserve_quality").green());
item.modelJson({
parent: "etcetera:block/prickly_can",
});
})
.model("etcetera:block/prickly_can")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 1);
blockInfo.serverTick(600, 0, (entity) => {
global.handlePicklingCan(entity);
}),
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.insertItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.insertItem(slot, stack, simulate)
)
.getSlotLimit((blockEntity, slot) =>
blockEntity.inventory.getSlotLimit(slot)
)
.getSlots((blockEntity) => blockEntity.inventory.slots)
.getStackInSlot((blockEntity, slot) =>
blockEntity.inventory.getStackInSlot(slot)
)
);
});
});
@@ -0,0 +1,69 @@
console.info("[SOCIETY] qualityWasher.js loaded");
global.handleQualityWasher = (e) => {
const { inventory, level, block } = e;
let slots = inventory.getSlots();
let slotItem;
let sentItem;
let belowItem;
const belowPos = block.getPos().below();
const belowBlock = level.getBlock(belowPos.x, belowPos.y, belowPos.z);
if (belowBlock.inventory && !inventory.isEmpty()) {
for (let i = 0; i < slots; i++) {
slotItem = inventory.getStackInSlot(i);
if (slotItem !== Item.of("minecraft:air")) {
for (let j = 0; j < belowBlock.inventory.slots; j++) {
belowItem = belowBlock.inventory.getStackInSlot(j);
if (
belowItem === Item.of("minecraft:air") ||
(belowItem === Item.of(slotItem.id) &&
belowItem.count < belowBlock.inventory.getSlotLimit(j))
) {
sentItem = slotItem.copy();
if (slotItem.nbt && slotItem.nbt.quality_food && !slotItem.hasTag('society:plushies')) {
sentItem.nbt = null;
}
sentItem.count = 1;
belowBlock.inventory.insertItem(j, sentItem, false);
slotItem.count--;
return;
}
}
}
}
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:quality_washer", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 0, 16, 16, 16)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.quality_washer.description").gray());
item.tooltip(Text.translatable("block.society.quality_washer.description.warn").red());
item.tooltip(Text.translatable("society.working_block_entity.can_use_hopper").green());
item.modelJson({
parent: "society:block/kubejs/quality_washer",
});
})
.model("society:block/kubejs/quality_washer")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 1);
blockInfo.serverTick(20, 0, (entity) => {
global.handleQualityWasher(entity);
}),
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.insertItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.insertItem(slot, stack, simulate)
)
.getSlotLimit((blockEntity, slot) => blockEntity.inventory.getSlotLimit(slot))
.getSlots((blockEntity) => blockEntity.inventory.slots)
.getStackInSlot((blockEntity, slot) => blockEntity.inventory.getStackInSlot(slot))
);
});
});
@@ -0,0 +1,286 @@
console.info("[SOCIETY] ribbitHut.js loaded");
const Block = Java.loadClass("net.minecraft.world.level.block.Block");
const getDrops = (block, blockState, level, pos, player) => {
if (block.id.includes("vinery")) {
let grape = block.getProperties().get("grape").split("_");
if (grape.length == 1) {
return [
Item.of(
`4x ${["crimson", "warped"].includes(grape[0]) ? "nethervinery" : "vinery"
}:${grape[0]}_grape`
),
];
}
return [Item.of(`4x vinery:${grape[0]}_grapes_${grape[1]}`)];
}
if (block.id.equals("windswept:wild_berry_bush")) {
return [Item.of(`2x windswept:wild_berries`)];
}
if (block.id.equals("autumnity:tall_foul_berry_bush")) {
return [Item.of(`2x autumnity:foul_berries`)];
}
return Block.getDrops(
blockState,
level,
pos,
null,
player,
Item.of("minecraft:hoe")
);
};
const getPlantData = (block, mcBlock, blockState) => {
let properties = block.getProperties();
if (
!properties ||
!properties.get("age") ||
["minecraft:torchflower", "minecraft:pitcher_crop"].includes(block.id)
) {
return {
maxAge: true,
};
}
if (
[
"windswept:wild_berry_bush",
"minecraft:sweet_berry_bush",
"autumnity:tall_foul_berry_bush",
].includes(block.id)
) {
return {
maxAge: properties.get("age").equals("3"),
newAge:
"minecraft:sweet_berry_bush".equals(block.id) ||
"autumnity:tall_foul_berry_bush".equals(block.id)
? "1"
: "2",
};
}
if ("society:mana_fruit_crop".equals(block.id))
return { maxAge: properties.get("age").equals("7"), newAge: "0" };
if ("vintagedelight:gearo_berry_bush".equals(block.id))
return { maxAge: properties.get("age").equals("4"), newAge: "2" };
if ("minecraft:cocoa".equals(block.id))
return { maxAge: properties.get("age").equals("2"), newAge: "0" };
if ("minecraft:nether_wart".equals(block.id))
return { maxAge: properties.get("age").equals("3"), newAge: "0" };
if (block.id.includes("vinery")) {
return {
maxAge: properties.get("age").equals("4"),
newAge: block.id.includes("lattice") ? "1" : "2",
};
}
if (["minecraft:melon_stem", "minecraft:pumpkin_stem"].includes(block.id)) {
return {
maxAge: false,
newAge: "0",
};
}
return { maxAge: mcBlock.isMaxAge(blockState), newAge: "0" };
};
const setHarvested = (level, pos, server, block, age) => {
let newProperties = block.getProperties();
if (age) {
newProperties.age = `${age}`;
block.set(block.id, newProperties);
} else {
block.set("minecraft:air");
}
const { x, y, z } = pos;
server.runCommandSilent(
`playsound minecraft:block.grass.break block @a ${x} ${y} ${z} 0.5`
);
level.spawnParticles(
"ribbits:spell",
true,
x + 0.5,
y + 0.5,
z + 0.5,
0,
0.1,
0,
1,
0.0001
);
};
global.handleRibbitHarvest = (tickEvent, pos, player, delay) => {
const { level, block } = tickEvent;
const server = level.server;
let blockState;
let drops;
let quality;
let scannedBlock;
let inserted = false;
let valid = true;
let plantData;
if (global.susFunctionLogging) console.log("[SOCIETY-SUSFN] ribbitHut.js");
server.scheduleInTicks(delay, () => {
if (!level.isLoaded(pos)) return;
scannedBlock = level.getBlock(pos);
if (scannedBlock && scannedBlock.hasTag("society:ribbit_hut_harvests")) {
blockState = level.getBlockState(pos);
plantData = getPlantData(scannedBlock, blockState.block, blockState);
if (
scannedBlock.id === "supplementaries:flax" &&
scannedBlock.getProperties().get("half") == "lower"
) {
valid = false;
}
if (valid && plantData.maxAge) {
drops = getDrops(scannedBlock, blockState, level, pos, player);
drops.forEach((drop) => {
quality = global.getCropQuality(scannedBlock);
// 4.0 TODO: remove effects:[] from this data
if (quality > 0) {
drop.nbt = `{quality_food:{effects:[],quality:${quality}}}`;
}
if (scannedBlock.id == "society:mana_fruit_crop") {
if (player.stages.has("paradise_crop")) drop.count += 1;
if (player.stages.has("crop_collector")) drop.count *= 2;
}
if (global.inventoryHasRoom(block, drop)) {
global.insertInto(block, drop);
inserted = true;
}
});
}
if (inserted) {
inserted = false;
if (scannedBlock.id === "supplementaries:flax") {
scannedBlock.set("minecraft:air");
level
.getBlock(pos.below())
.set("supplementaries:flax", { age: "0", half: "lower" });
} else {
setHarvested(level, pos, server, scannedBlock, plantData.newAge);
}
}
}
});
};
global.runRibbitHut = (tickEvent) => {
const { level, block } = tickEvent;
let centerBlock = global.getOpposite(
block.getProperties().get("facing"),
block.getPos()
);
const { x, y, z } = centerBlock;
let scannedBlocks = 0;
let attachedPlayer;
let dayTime = level.dayTime();
let morningModulo = dayTime % 24000;
const ribbitHutProgTime = 1000;
if (
morningModulo >= ribbitHutProgTime &&
morningModulo < ribbitHutProgTime + artMachineTickRate
) {
level.getServer().players.forEach((p) => {
if (p.getUuid().toString() === block.getEntityData().data.owner) {
attachedPlayer = p;
}
});
if (attachedPlayer) {
level.server.runCommandSilent(
`playsound ribbits:entity.ribbit.ambient block @a ${x} ${y} ${z}`
);
for (let pos of BlockPos.betweenClosed(
new BlockPos(x - 7, y - 1, z - 7),
[x + 7, y + 1, z + 7]
)) {
global.handleRibbitHarvest(
tickEvent,
pos.immutable(),
attachedPlayer,
scannedBlocks
);
scannedBlocks++;
}
}
}
};
StartupEvents.registry("block", (e) => {
e.create("society:ribbit_hut", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.soundType("shroomlight")
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.ribbit_hut.description").gray()
);
item.tooltip(
Text.translatable(
"society.working_block_entity.apply_player_skill"
).gray()
);
item.tooltip(
Text.translatable("tooltip.society.area", `15x3x15`).green()
);
item.modelJson({
parent: "minecraft:item/generated",
textures: {
layer0: "society:item/ribbit_hut_item",
},
});
})
.lightLevel(1)
.property(booleanProperty.create("upgraded"))
.defaultState((state) => {
state.set(booleanProperty.create("upgraded"), false);
})
.placementState((state) => {
state.set(booleanProperty.create("upgraded"), false);
})
.soundType("stone")
.model("society:block/kubejs/ribbit_hut/bottom_front_center")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 3);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(artMachineTickRate, 0, (entity) => {
global.runRibbitHut(entity);
}),
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)
)
);
});
e.create("society:ribbit_hut_block", "cardinal")
.property(integerProperty.create("layer", 0, 2))
.property(integerProperty.create("depth", 0, 2))
.property(integerProperty.create("side", 0, 2))
.defaultState((state) => {
state.set(integerProperty.create("layer", 0, 2), 0);
state.set(integerProperty.create("depth", 0, 2), 0);
state.set(integerProperty.create("side", 0, 2), 1);
})
.placementState((state) => {
state.set(integerProperty.create("layer", 0, 2), 0);
state.set(integerProperty.create("depth", 0, 2), 0);
state.set(integerProperty.create("side", 0, 2), 1);
})
.resistance(3600000)
.unbreakable()
.item((item) => {
item.modelJson({
parent: "ribbits:item/toadstool",
});
})
.tagBlock("minecraft:mineable/axe")
.tagBlock("minecraft:needs_stone_tool")
.defaultCutout()
.soundType("stone");
});
@@ -0,0 +1,129 @@
// priority: -21
console.info("[SOCIETY] roeRecycler.js loaded");
global.handleRoeRecycler = (e) => {
const { inventory, level, block } = e;
const { x, y, z } = block;
let slots = inventory.getSlots();
let slotItem;
const belowPos = block.getPos().below();
const belowBlock = level.getBlock(belowPos.x, belowPos.y, belowPos.z);
if (rnd10() && belowBlock.inventory && !inventory.isEmpty()) {
for (let i = 0; i < slots; i++) {
slotItem = inventory.getStackInSlot(i);
if (
slotItem !== Item.of("minecraft:air") &&
slotItem.id.includes("_roe") &&
!slotItem.id.includes("aged_")
) {
let roeOutputs = [];
let fish = global.fishPondDefinitions.get(
global.getFishFromRoe(slotItem.id)
);
if (fish && fish.additionalRewards) {
let fishPondRoll = 0;
let population = rnd(1, 10);
fish.additionalRewards.forEach((reward) => {
fishPondRoll = Math.random();
if (
population >= reward.minPopulation &&
fishPondRoll <= reward.chance / 2
) {
let calculateCount = Math.floor(
Math.max(1, reward.count / 4) *
((population - reward.minPopulation) /
(10 - reward.minPopulation))
);
if (population == 10) calculateCount = reward.count;
roeOutputs.push(
`${calculateCount > 1 ? calculateCount : 1}x ${reward.item}`
);
}
});
}
if (roeOutputs.length == 0 && rnd10()) {
roeOutputs.push("1x aquaculture:algae");
}
let hasRoom = true;
roeOutputs.forEach((item) => {
if (!global.inventoryBelowHasRoom(level, block, item)) {
hasRoom = false;
}
});
if (hasRoom) {
roeOutputs.forEach((item) => {
global.insertBelow(level, block, item);
});
slotItem.count--;
level.server.runCommandSilent(
`playsound supplementaries:item.bubble_blower block @a ${block.x} ${block.y} ${block.z}`
);
level.spawnParticles(
"supplementaries:suds",
true,
x + 0.5,
y + 1,
z + 0.5,
0.1 * rnd(1, 2),
0.1 * rnd(1, 2),
0.1 * rnd(1, 2),
rnd(2, 6),
0.001
);
break;
}
}
}
}
level.spawnParticles(
"domesticationinnovation:simple_bubble",
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
);
};
StartupEvents.registry("block", (event) => {
event
.create("society:roe_recycler", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 0, 16, 16, 16)
.defaultCutout()
.item((item) => {
item.tooltip(
Text.translatable("block.society.roe_recycler.description").gray()
);
item.modelJson({
parent: "society:block/kubejs/roe_recycler",
});
})
.model("society:block/kubejs/roe_recycler")
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 1);
blockInfo.serverTick(20, 0, (entity) => {
global.handleRoeRecycler(entity);
}),
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.insertItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.insertItem(slot, stack, simulate)
)
.getSlotLimit((blockEntity, slot) =>
blockEntity.inventory.getSlotLimit(slot)
)
.getSlots((blockEntity) => blockEntity.inventory.slots)
.getStackInSlot((blockEntity, slot) =>
blockEntity.inventory.getStackInSlot(slot)
)
);
});
});
@@ -0,0 +1,63 @@
console.info("[SOCIETY] shippingBinMonitor.js loaded");
global.runShippingBinMonitor = (entity) => {
const { level, block } = entity;
const belowPos = block.getPos().below();
const belowBlock = level.getBlock(belowPos.x, belowPos.y, belowPos.z);
if (belowBlock.hasTag("society:shipping_bin")) {
let slots = belowBlock.inventory.getSlots();
global.cacheShippingBin(entity);
let blockData = belowBlock.getEntityData().data;
let playerAttributes = blockData.attributes;
let playerStages = blockData.stages;
let calculationResults = -1;
if (!playerStages || !playerAttributes) return;
calculationResults = Math.round(
global.processShippingBinInventory(
belowBlock.inventory,
slots,
playerAttributes,
playerStages,
false,
true
).calculatedValue
);
let nbt = block.getEntityData();
if (nbt.data.value !== calculationResults) {
nbt.merge({ data: { value: calculationResults } });
global.setBlockEntityData(block, nbt)
global.clearOldTextDisplay(block, level, "shipping_bin_monitor");
global.spawnTextDisplay(
block,
block.y + 0.25,
"shipping_bin_monitor",
calculationResults === -1
? Text.translatable("block.society.shipping_bin_monitor.offline")
: Text.of(`${calculationResults < 100000000 ? " " : ""}${global.formatPrice(calculationResults)}`)
);
}
}
};
StartupEvents.registry("block", (event) => {
event
.create("society:shipping_bin_monitor", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.defaultCutout()
.box(0, 0, 0, 16, 3, 16)
.item((item) => {
item.tooltip(Text.translatable("block.society.shipping_bin_monitor.description").gray());
item.modelJson({
parent: "society:block/kubejs/shipping_bin_monitor",
});
})
.model("society:block/kubejs/shipping_bin_monitor")
.blockEntity((blockInfo) => {
blockInfo.initialData({ value: 0 });
blockInfo.serverTick(200, 0, (entity) => global.runShippingBinMonitor(entity));
})
.rightClick((click) => {
global.runShippingBinMonitor({ block: click.block, level: click.level });
});
});
@@ -0,0 +1,98 @@
// priority: 1
console.info("[SOCIETY] smartShippingBin.js loaded");
StartupEvents.registry("block", (event) => {
event
.create("shippingbin:smart_shipping_bin", "cardinal")
.tagBlock("minecraft:mineable/axe")
.item((item) => {
item.tooltip(
Text.translatable("tooltip.society.smart_shipping_bin").gray()
);
item.tooltip(
Text.translatable("tooltip.society.smart_shipping_bin.warn").red()
);
item.modelJson({
parent: "society:block/kubejs/smart_shipping_bin",
});
})
.blockEntity((blockInfo) => {
blockInfo.inventory(9, 6);
blockInfo.initialData({ owner: "-1" });
blockInfo.serverTick(4000, 0, (entity) => {
const { inventory, block, level } = entity;
if (global.susFunctionLogging) console.log("[SOCIETY-SUSFN] smartShippingBin.js");
let slots = entity.inventory.getSlots();
let value = 0;
let binPlayer = global.cacheShippingBin(entity);
let blockData = block.getEntityData().data;
let playerAttributes = blockData.attributes;
let playerStages = blockData.stages;
let ownerUUID = blockData.owner;
if (!playerStages || !playerAttributes) return;
value = global.processShippingBinInventory(
inventory,
slots,
playerAttributes,
playerStages
).calculatedValue;
global.processValueOutput(
value,
slots,
undefined,
binPlayer,
level.getServer(),
block,
inventory,
true,
ownerUUID
);
}),
blockInfo.rightClickOpensInventory();
blockInfo.attachCapability(
CapabilityBuilder.ITEM.blockEntity()
.insertItem((blockEntity, slot, stack, simulate) =>
blockEntity.inventory.insertItem(slot, stack, simulate)
)
.getSlotLimit((blockEntity, slot) => blockEntity.inventory.getSlotLimit(slot))
.getSlots((blockEntity) => blockEntity.inventory.slots)
.getStackInSlot((blockEntity, slot) => blockEntity.inventory.getStackInSlot(slot))
);
}).blockstateJson = {
multipart: [
{
when: { facing: "north" },
apply: {
model: "society:block/kubejs/smart_shipping_bin",
y: 0,
uvlock: false,
},
},
{
when: { facing: "east" },
apply: {
model: "society:block/kubejs/smart_shipping_bin",
y: 90,
uvlock: false,
},
},
{
when: { facing: "south" },
apply: {
model: "society:block/kubejs/smart_shipping_bin",
y: 180,
uvlock: false,
},
},
{
when: { facing: "west" },
apply: {
model: "society:block/kubejs/smart_shipping_bin",
y: -90,
uvlock: false,
},
},
],
};
});
@@ -0,0 +1,49 @@
console.info("[SOCIETY] snowMelter.js loaded");
global.handleSnowMelter = (entity) => {
const { block, level } = entity;
if (block.level.hasNeighborSignal(block.pos)) return;
const { x, y, z } = block;
const radius = 10;
const verticalRadius = 2;
let scanBlock;
if (global.susFunctionLogging) console.log('[SOCIETY-SUSFN] snowMelter.js')
for (let pos of BlockPos.betweenClosed(new BlockPos(x - radius, y - verticalRadius, z - radius), [
x + radius,
y + verticalRadius,
z + radius,
])) {
if (!level.isLoaded(pos)) continue;
scanBlock = level.getBlock(pos);
if (scanBlock.id === "minecraft:snow") {
scanBlock.set("minecraft:air");
}
if (scanBlock.id === "snowrealmagic:snow") {
scanBlock.set(scanBlock.getEntityData().Block);
}
if (scanBlock.id === "minecraft:ice") {
scanBlock.set("minecraft:water");
}
}
};
StartupEvents.registry("block", (e) => {
e.create("society:snow_melter", "cardinal")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:needs_stone_tool")
.box(0, 0, 0, 16, 16, 16)
.defaultCutout()
.item((item) => {
item.tooltip(Text.translatable("block.society.snow_melter.description").gray());
item.tooltip(Text.translatable("tooltip.society.area", `19x5x19`).green());
item.modelJson({
parent: "society:block/kubejs/snow_melter",
});
})
.model("society:block/kubejs/snow_melter")
.blockEntity((blockInfo) => {
blockInfo.serverTick(600, 0, (entity) => {
global.handleSnowMelter(entity);
});
});
});
@@ -0,0 +1 @@
// REMOVED
@@ -0,0 +1,22 @@
console.info("[SOCIETY] villagerHome.js loaded");
StartupEvents.registry("block", (event) => {
event
.create("society:villager_home")
.tagBlock("minecraft:mineable/pickaxe")
.tagBlock("minecraft:mineable/axe")
.tagBlock("minecraft:needs_stone_tool")
.box(1, 0, 1, 15, 2, 15)
.defaultCutout()
.item((item) => {
item.tooltip(Text.gray("Brings the invited villager to its housing and sets its home point."));
item.modelJson({
parent: "society:block/kubejs/villager_home",
});
})
.model("society:block/kubejs/villager_home")
.blockEntity((blockInfo) => {
blockInfo.enableSync();
blockInfo.initialData({ placer: "-1", type: "", spawned: false });
});
});