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,783 @@
// Why are entity type tags so weird
global.checkEntityTag = (entity, checkedTag) => {
if (!entity || !entity.entityType || !entity.entityType.tags) return false;
return entity.entityType.tags.anyMatch((tag) => tag.location() == checkedTag);
};
global.isFresh = (day, actionAge) => {
return day < actionAge;
};
global.getAnimalIsNotCramped = (target, scale, applyGlowing) => {
const level = target.getLevel();
const entities = level
.getEntitiesWithin(target.boundingBox.inflate(scale))
.filter((e) => global.checkEntityTag(e, "society:husbandry_animal"));
let cramped = entities.length > 5
if (cramped && applyGlowing) {
entities.forEach((entity) => {
entity.potionEffects.add("minecraft:glowing", 200, 0, false, false);
})
}
return !cramped;
};
global.isWarpedCow = (target) => {
if (target.type === "meadow:wooly_cow") {
if (target.toString().includes("WoolyCowEntity")) return Number(target.getNbt().Variant) === 2
let variant = target.Variant
if (variant && Number(variant) === 2) return true;
}
return false;
}
global.getMilkingTimeMult = (target, type) => {
const warped = global.isWarpedCow(target);
let mult;
global.husbandryMilkingDefinitions.forEach((definition) => {
if (!mult && definition.animal.equals(type.toString())) {
if (warped && definition.warped) mult = definition.cooldown;
if (!warped) mult = definition.cooldown;
}
});
return mult;
};
global.getHusbandryQuality = (hearts, mood, milk) => {
let heartQuality = 0;
let moodQuality = 0;
if (hearts > 0) {
if (milk) {
if (hearts >= 10 || (hearts > 0 && hearts % 5 === 0)) {
heartQuality = 3;
} else {
heartQuality = Math.floor((hearts % 11) / 2 - 2);
}
} else {
if (hearts >= 10) {
heartQuality = 3;
} else {
heartQuality = Math.floor((hearts % 11) / 2 - 2);
}
}
}
if (mood > 224) moodQuality = 3;
else if (mood > 192) moodQuality = 2;
else if (mood > 160) moodQuality = 1;
return Math.min(moodQuality, heartQuality);
};
const resolveMilk = (hearts, mood, target, type) => {
let large = hearts > 5 && Math.random() < (mood + hearts * 10) / 256;
let milk;
const warped = global.isWarpedCow(target);
global.husbandryMilkingDefinitions.forEach((definition) => {
if (!milk && definition.animal.equals(type.toString())) {
if (warped && definition.warped)
milk = large ? definition.milk.lg : definition.milk.sm;
if (!warped) milk = large ? definition.milk.lg : definition.milk.sm;
}
});
return milk;
};
const canMilk = (data, target, day, plushieModifiers) => {
const ageLastMilked = data.getInt("ageLastMilked");
const dayHasPassed =
day > ageLastMilked + global.getMilkingTimeMult(target, target.type) - 1;
const freshAnimal = global.isFresh(day, ageLastMilked);
if (plushieModifiers) return freshAnimal || dayHasPassed;
const hungry = global.compareDay(day, data.getInt("ageLastFed"), 1)
return !target.isBaby() && !hungry && (freshAnimal || dayHasPassed);
};
/**
* @param {Internal.Player|null} player
* player.stages, or auto-grabber NBT stages, or empty stages for mana milker
* @param {Internal.Stages|SocietyStages} stages
*/
global.getMilk = (
level,
target,
data,
player,
day,
raiseAffection,
plushieModifiers,
stages
) => {
const crackerBonus = data.animalCracker ? 2 : 1;
let affection;
let mood;
let affectionIncrease = 0;
if (plushieModifiers) {
affection = 1000;
mood = 256;
} else {
affection = data.getInt("affection") || 0;
mood = global.getOrFetchMood(level, target, day, player);
affectionIncrease = stages.has("animal_whisperer") || data.bribed ? 10 : 5;
}
let hearts = Math.floor(affection / 100);
let quality = 0;
if (canMilk(data, target, day, plushieModifiers)) {
const plushieDoubleDrops = plushieModifiers && plushieModifiers.doubleDrops;
const plushieProcessItems =
plushieModifiers && plushieModifiers.processItems;
if (raiseAffection) data.affection = affection + affectionIncrease;
if (!plushieModifiers) data.ageLastMilked = day;
if (mood >= 160) {
quality = global.getHusbandryQuality(hearts, mood, true);
}
let milkId = resolveMilk(hearts, mood, target, target.type);
if (milkId == "species:ichor_bottle" && hearts >= 5) quality = 3;
if (plushieProcessItems) {
let cheesePressOutput = global.cheesePressRecipes.get(milkId);
if (cheesePressOutput) {
milkId = Item.of(cheesePressOutput.output[0]).id;
}
}
return Item.of(
`${(stages.has("shepherd") ? 2 : 1) *
crackerBonus *
(plushieDoubleDrops ? 2 : 1)
}x ${milkId}`,
quality > 0 ? `{quality_food:{effects:[],quality:${quality}}}` : null
);
}
return -1;
};
/**
* @param {Internal.Player|null} player
* @param {Internal.Stages|SocietyStages} stages player.stages or auto-grabber NBT stages
*/
global.handleSpecialHarvest = (
level,
target,
player,
server,
block,
inventory,
plushieModifiers,
harvestFunction,
stages
) => {
const day = global.getDay(level);
const data = plushieModifiers ? target : target.persistentData;
const ageLastFed = plushieModifiers ? -1 : data.getInt("ageLastFed");
const ageLastDroppedSpecial = data.getInt("ageLastDroppedSpecial") || 0;
const type = target.type;
const freshAnimal = global.isFresh(day, ageLastDroppedSpecial);
const hungry = global.compareDay(day, ageLastFed, 1)
const crackerBonus = data.animalCracker ? 2 : 1;
if (freshAnimal || day > ageLastDroppedSpecial) {
let resolvedCount;
let resolvedItem;
global.husbandryForagingDefinitions.forEach((definition) => {
if (definition.animal.equals(type)) {
definition.forages.forEach((forage) => {
resolvedCount = forage.countMult;
if (forage.stage && stages.has(forage.stage.name)) {
resolvedCount = forage.stage.newCountMult;
}
if (forage.itemPool) {
resolvedItem =
forage.itemPool[
Math.floor(Math.random() * forage.itemPool.length)
];
} else {
resolvedItem = forage.item;
}
harvestFunction(
data,
day,
forage.chance,
hungry,
forage.minHearts,
resolvedCount * crackerBonus,
resolvedItem,
forage.hasQuality,
plushieModifiers,
{
level: level,
target: target,
player: player,
server: server,
block: block,
inventory: inventory,
}
);
});
}
});
if (
stages.has("coopmaster") &&
(plushieModifiers
? global.coopMasterAnimals.includes(data.type)
: global.checkEntityTag(target, "society:coopmaster_bird"))
) {
harvestFunction(
data,
day,
0.02,
hungry,
1,
1 * crackerBonus,
"vintagedelight:golden_egg",
true,
plushieModifiers,
{
level: level,
target: target,
player: player,
server: server,
block: block,
inventory: inventory,
}
);
}
if (data.bff && stages.has("bff")) {
harvestFunction(
data,
day,
0.1,
hungry,
10,
1 * crackerBonus,
"society:prismatic_shard",
false,
plushieModifiers,
{
level: level,
target: target,
player: player,
server: server,
block: block,
inventory: inventory,
}
);
}
if (player && !player.isFake() && !stages.has("animal_fancy")) {
harvestFunction(
data,
day,
0.05,
hungry,
4,
1,
"society:animal_fancy",
false,
plushieModifiers,
{
level: level,
target: target,
player: player,
server: server,
block: block,
inventory: inventory,
}
);
}
if (stages.has("reaping_scythe")) {
harvestFunction(
data,
day,
0.1,
hungry,
1,
1 * crackerBonus,
"quark:diamond_heart",
false,
plushieModifiers,
{
level: level,
target: target,
player: player,
server: server,
block: block,
inventory: inventory,
}
);
}
if (
plushieModifiers &&
plushieModifiers.newDrops &&
plushieModifiers.newDrops.length > 0
) {
plushieModifiers.newDrops.forEach((drop) => {
harvestFunction(
data,
day,
1,
hungry,
1,
drop.count * crackerBonus,
drop.id,
false,
plushieModifiers,
{
level: level,
target: target,
player: player,
server: server,
block: block,
inventory: inventory,
}
);
});
}
if (!plushieModifiers) data.ageLastDroppedSpecial = day;
}
};
/**
* @param {Internal.Player|null} player
* player.stages, or auto grabber NBT stages, or empty stages for mana milker
* @param {Internal.Stages|SocietyStages} stages
*/
global.getMagicShearsOutput = (level, target, player, plushieModifiers, stages) => {
const day = global.getDay(level);
const data = plushieModifiers ? target : target.persistentData;
const ageLastMagicHarvested = data.getInt("ageLastMagicHarvested");
const freshAnimal = global.isFresh(day, ageLastMagicHarvested);
let affection;
let mood;
if (plushieModifiers) {
affection = 1000;
mood = 256;
} else {
affection = data.getInt("affection") || 0;
mood = global.getOrFetchMood(level, target, day, player);
}
let hearts = Math.floor((affection > 1000 ? 1000 : affection) / 100);
const targetId =
target.type === "meadow:wooly_cow"
? ["minecraft", "cow"]
: target.type.split(":");
const droppedLoot = Utils.rollChestLoot(
`${targetId[0]}:entities/${targetId[1]}`
).toArray();
let newLoot = [];
if (hearts >= 5 && (freshAnimal || day > ageLastMagicHarvested)) {
if (!plushieModifiers || !plushieModifiers.resetDay) {
data.ageLastMagicHarvested = day;
}
data.affection = affection - 7;
if (!plushieModifiers) {
level.spawnParticles(
"snowyspirit:glow_light",
true,
target.x,
target.y + 1.5,
target.z,
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
20,
2
);
}
if (mood >= 160) {
let quality = global.getHusbandryQuality(hearts, mood);
for (let i = 0; i < droppedLoot.length; i++) {
droppedLoot[i] = Item.of(
droppedLoot[i].id,
`{quality_food:{effects:[],quality:${quality}}}`
);
}
}
if (stages.has("mana_hand")) {
let dropItem;
for (let i = 0; i < droppedLoot.length; i++) {
dropItem = droppedLoot[i];
if (dropItem.maxStackSize < dropItem.count * 2) {
newLoot.push(dropItem);
newLoot.push(dropItem);
} else {
dropItem.count = dropItem.count * 2;
newLoot.push(dropItem);
}
}
return newLoot;
}
for (let i = 0; i < droppedLoot.length; i++) {
newLoot.push(droppedLoot[i]);
}
if (stages.has("heretic")) {
newLoot.push(Item.of("3x society:sparkstone"));
if (!plushieModifiers) {
target.attack(2);
data.affection = affection - 20;
}
}
return newLoot;
} else return -1;
};
const getMoodImpactModifier = (target) => {
if (global.tierTwoHusbandryAnimals.includes(target.type)) return 1.25;
if (global.tierThreeHusbandryAnimals.includes(target.type)) return 1.5;
return 1;
};
const getNearbyBlocks = (level, target, radius, tag) => {
const { x, y, z } = target;
let blockCount = 0;
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(tag)) {
blockCount++;
}
}
return blockCount;
};
/**
* @param {Internal.Player|null} player
*/
global.getOrFetchMood = (level, target, day, player, debugMood, disregardPet) => {
if (global.checkEntityTag(target, "society:pet_animal")) return 256;
const data = target.persistentData;
let moodDebuffs = 0;
let moodImpactModifier = getMoodImpactModifier(target);
if (!player && debugMood) {
console.log("getOrFetchMood: cannot debug mood because player is falsey!");
debugMood = false;
}
if (moodImpactModifier > 1 && debugMood) player.tell(Text.translatable("society.husbandry.mood.breed_impact", moodImpactModifier).gold());
if (!disregardPet && global.compareDay(day, data.getInt("ageLastPet"), 1)) {
moodDebuffs += 96;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.not_pet").red());
}
if (global.compareDay(day, data.getInt("ageLastFed"), 2)) {
moodDebuffs += 128;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.not_fed").red());
}
let requiredBlocks = 0;
if (global.coldMobs.includes(target.type)) {
requiredBlocks = getNearbyBlocks(level, target, 5, "society:cold_blocks");
if (requiredBlocks < 5) {
let coldDebuff = 32 - (32 * requiredBlocks) / 5
moodDebuffs += coldDebuff;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.not_cold", coldDebuff).red());
}
} else {
if (
global.getSeasonFromBiome(level, target.getPos()) === "winter" &&
level.canSeeSky(target.getPos())
) {
moodDebuffs += 32;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.too_cold").red());
}
}
if (!global.getAnimalIsNotCramped(target, 1.1, debugMood)) {
moodDebuffs += 96;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.cramped").red());
}
if (level.raining && level.canSeeSky(target.getPos())) {
moodDebuffs += 32;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.wet").red());
}
let baseDebuffs = moodDebuffs
moodDebuffs *= moodImpactModifier;
if (day - data.getInt("ageLastBoosted") == 1) {
moodDebuffs -= 24;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.boosted_food").green());
}
if (data.clockwork) {
moodDebuffs -= 64;
if (debugMood) player.tell(Text.translatable("society.husbandry.mood.clockwork").green());
}
if (debugMood) {
if (baseDebuffs > 0) player.tell(Text.translatable("society.husbandry.mood.total_debuffs", Number(baseDebuffs)).darkRed());
player.tell(Text.translatable("society.husbandry.mood.final_mood", Number(256 - moodDebuffs)).gray());
}
if (global.compareDay(day, data.getInt("ageLastSetMood"), 1)) {
data.lastMood = Math.max(0, 256 - moodDebuffs);
data.ageLastSetMood = day;
}
return data.lastMood;
};
/**
* Plushie Trait related drops and mechanics
*/
global.getPlushieModifiers = (level, data, plushieBlock) => {
let newDrops = [];
let doubleDrops = false;
let resetDay = false;
let qualityMult = data.quality + 1;
let probabilityIncrease = 0;
let processItems = false;
const roll = Math.random();
switch (data.type) {
case 0:
// Aquatic
if (roll < 0.05 * qualityMult) {
newDrops.push(
Item.of(rnd50() ? "society:river_jelly" : "society:ocean_jelly")
);
}
break;
case 1:
// Woodsy
let nearbyLogs = global.getTaggedBlocksInRadius(
level,
"society:raw_logs",
plushieBlock,
7,
true
);
if (nearbyLogs.length > 0) {
newDrops.push(
Item.of(
`${qualityMult * 8}x ${nearbyLogs[Math.floor(Math.random() * nearbyLogs.length)]
}`
)
);
}
break;
case 2:
// Eldritch
newDrops.push(Item.of(`${qualityMult}x oreganized:raw_silver`));
break;
case 3:
// Wrathful
newDrops.push(Item.of(`${qualityMult * 3}x oreganized:raw_lead`));
break;
case 4:
// Sommelier
if (roll < 0.25 * qualityMult) processItems = true;
break;
case 5:
// Sunlit
if (roll < (0.05 * qualityMult)) {
newDrops.push(Item.of("society:sunlit_crystal"));
}
break;
case 6:
// Hungry
if (roll < 0.1 * qualityMult) resetDay = true;
break;
case 7:
// Anxious
probabilityIncrease = 0.25 * qualityMult;
break;
case 8:
// Shy
if (
global.getTaggedBlocksInRadius(
level,
"society:plushies",
plushieBlock,
3 - (qualityMult - 1)
) == 1
) {
doubleDrops = true;
}
break;
case 9:
// Cheerful;
if (
global.getTaggedBlocksInRadius(
level,
"society:plushies",
plushieBlock,
2
) >
28 - 4 * qualityMult
) {
doubleDrops = true;
}
break;
case 10:
// Chill
newDrops.push(Item.of(`${qualityMult}x society:pristine_diamond`));
break;
case 11:
// Machiavellian
newDrops.push(Item.of(`${qualityMult}x minecraft:netherite_scrap`));
break;
case 12:
// Cutesy
newDrops.push(Item.of(`${qualityMult}x society:furniture_box`));
break;
case 13:
// Fashionista
if (
global.getTaggedBlocksInRadius(
level,
"society:loot_furniture",
plushieBlock,
2
) >=
28 - 4 * qualityMult
) {
doubleDrops = true;
}
break;
default:
case 14:
// Neutral
if (roll < 0.1 * qualityMult) doubleDrops = true;
break;
}
return {
newDrops: newDrops,
doubleDrops: doubleDrops,
resetDay: resetDay,
probabilityIncrease: probabilityIncrease,
processItems: processItems,
};
};
// const { newDrops, doubleDrops, resetDay, probabilityIncrease, processItems } =
// global.getPlushieDrops(plushieNbt, plushie);
global.executePlushieHusbandry = (
level,
server,
player,
item,
block,
specialHarvestFunction
) => {
let nbt = block.getEntityData();
const { animal } = nbt.data;
if (!animal) return;
let reset = false;
const day = global.getDay(level);
const plushieMods = global.getPlushieModifiers(level, nbt.data, block);
if (
item === "society:milk_pail" &&
global.milkableAnimals.includes(animal.type)
) {
let milkItem = global.getMilk(
level,
animal,
animal,
player,
day,
false,
plushieMods,
player.stages,
);
if (milkItem !== -1) {
let milk = level.createEntity("minecraft:item");
milk.x = player.x;
milk.y = player.y;
milk.z = player.z;
milk.item = milkItem;
milk.spawn();
server.runCommandSilent(
`playsound minecraft:entity.cow.milk block @a ${player.x} ${player.y} ${player.z}`
);
global.giveExperience(server, player, "husbandry", 30);
if (!plushieMods.resetDay) {
nbt.merge({
data: {
animal: {
ageLastMilked: day,
},
},
});
} else {
reset = true;
}
level.spawnParticles(
"minecraft:note",
true,
block.x,
block.y + 1.5,
block.z,
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
0.1 * rnd(1, 4),
3,
0.01
);
}
}
global.handleSpecialHarvest(
level,
animal,
player,
server,
block,
undefined,
plushieMods,
specialHarvestFunction,
player.stages,
);
if (!plushieMods.resetDay) {
nbt.merge({
data: {
animal: {
ageLastDroppedSpecial: day,
},
},
});
} else if (Number(animal.ageLastDroppedSpecial) < day) {
reset = true;
}
if (item === "society:magic_shears") {
const droppedLoot = global.getMagicShearsOutput(
level,
animal,
player,
plushieMods,
player.stages,
);
if (droppedLoot !== -1) {
server.runCommandSilent(
`playsound minecraft:entity.sheep.shear block @a ${player.x} ${player.y} ${player.z}`
);
for (let i = 0; i < droppedLoot.length; i++) {
let specialItem = level.createEntity("minecraft:item");
let dropItem = droppedLoot[i];
specialItem.x = player.x;
specialItem.y = player.y;
specialItem.z = player.z;
specialItem.item = dropItem;
specialItem.spawn();
}
level.spawnParticles(
"snowyspirit:glow_light",
true,
block.x,
block.y + 0.5,
block.z,
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
20,
2
);
global.addItemCooldown(player, item, 1);
}
}
global.setBlockEntityData(block, nbt)
if (reset) {
server.runCommandSilent(
`playsound legendarycreatures:corpse_eater_death block @a ${block.x} ${block.y} ${block.z}`
);
level.spawnParticles(
"species:spectre_smoke",
true,
block.x,
block.y,
block.z,
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
0.2 * rnd(1, 4),
3,
0.01
);
}
};