first smoketestable

This commit is contained in:
petrak@ 2023-01-22 23:59:19 -06:00
parent edc4012f69
commit aca2c19be6
51 changed files with 474 additions and 381 deletions

View file

@ -1,26 +0,0 @@
package at.petrak.hexcasting.api.misc;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public enum ScrollQuantity {
NONE(null, 0),
FEW(modLoc("inject/scroll_loot_few"), 2),
SOME(modLoc("inject/scroll_loot_some"), 3),
MANY(modLoc("inject/scroll_loot_many"), 4);
private final ResourceLocation pool;
public final int countRange;
ScrollQuantity(ResourceLocation pool, int countRange) {
this.pool = pool;
this.countRange = countRange;
}
@Nullable
public ResourceLocation getPool() {
return pool;
}
}

View file

@ -2,7 +2,6 @@ package at.petrak.hexcasting.api.mod;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.misc.MediaConstants;
import at.petrak.hexcasting.api.misc.ScrollQuantity;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Tier;
@ -60,18 +59,11 @@ public class HexConfig {
// fun fact, although dimension keys are a RegistryHolder, they aren't a registry, so i can't do tags
boolean canTeleportInThisDimension(ResourceKey<Level> dimension);
ScrollQuantity scrollsForLootTable(ResourceLocation lootTable);
int DEFAULT_MAX_RECURSE_DEPTH = 512;
int DEFAULT_MAX_SPELL_CIRCLE_LENGTH = 1024;
int DEFAULT_OP_BREAK_HARVEST_LEVEL = 3;
boolean DEFAULT_VILLAGERS_DISLIKE_MIND_MURDER = true;
List<String> DEFAULT_FEW_SCROLL_TABLES = List.of("minecraft:chests/jungle_temple",
"minecraft:chests/simple_dungeon", "minecraft:chests/village/village_cartographer");
List<String> DEFAULT_SOME_SCROLL_TABLES = List.of("minecraft:chests/bastion_treasure",
"minecraft:chests/shipwreck_map");
List<String> DEFAULT_MANY_SCROLL_TABLES = List.of("minecraft:chests/stronghold_library");
List<String> DEFAULT_DIM_TP_DENYLIST = List.of("twilightforest:twilight_forest");

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.lib;
import at.petrak.hexcasting.common.loot.AddPerWorldPatternToScrollFunc;
import at.petrak.hexcasting.common.loot.AmethystReducerFunc;
import at.petrak.hexcasting.common.loot.PatternScrollFunc;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
@ -21,7 +21,7 @@ public class HexLootFunctions {
private static final Map<ResourceLocation, LootItemFunctionType> LOOT_FUNCS = new LinkedHashMap<>();
public static final LootItemFunctionType PATTERN_SCROLL = register("pattern_scroll",
new LootItemFunctionType(new PatternScrollFunc.Serializer()));
new LootItemFunctionType(new AddPerWorldPatternToScrollFunc.Serializer()));
public static final LootItemFunctionType AMETHYST_SHARD_REDUCER = register("amethyst_shard_reducer",
new LootItemFunctionType(new AmethystReducerFunc.Serializer()));

View file

@ -14,15 +14,20 @@ import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
/**
* Slap a random per-world pattern on the scroll
* Slap a random per-world pattern on the scroll.
* <p>
* The function itself is only used on Fabric but the behavior {@link AddPerWorldPatternToScrollFunc#doStatic}
* is used on both sides
*/
public class PatternScrollFunc extends LootItemConditionalFunction {
public PatternScrollFunc(LootItemCondition[] lootItemConditions) {
public class AddPerWorldPatternToScrollFunc extends LootItemConditionalFunction {
public AddPerWorldPatternToScrollFunc(LootItemCondition[] lootItemConditions) {
super(lootItemConditions);
}
@Override
protected ItemStack run(ItemStack stack, LootContext ctx) {
/**
* This doesn't actually have any params so extract behaviour out for the benefit of forge
*/
public static ItemStack doStatic(ItemStack stack, LootContext ctx) {
var rand = ctx.getRandom();
var worldLookup = PatternRegistryManifest.getAllPerWorldActions();
@ -39,21 +44,26 @@ public class PatternScrollFunc extends LootItemConditionalFunction {
return stack;
}
@Override
protected ItemStack run(ItemStack stack, LootContext ctx) {
return doStatic(stack, ctx);
}
@Override
public LootItemFunctionType getType() {
return HexLootFunctions.PATTERN_SCROLL;
}
public static class Serializer extends LootItemConditionalFunction.Serializer<PatternScrollFunc> {
public static class Serializer extends LootItemConditionalFunction.Serializer<AddPerWorldPatternToScrollFunc> {
@Override
public void serialize(JsonObject json, PatternScrollFunc value, JsonSerializationContext ctx) {
public void serialize(JsonObject json, AddPerWorldPatternToScrollFunc value, JsonSerializationContext ctx) {
super.serialize(json, value, ctx);
}
@Override
public PatternScrollFunc deserialize(JsonObject object, JsonDeserializationContext ctx,
public AddPerWorldPatternToScrollFunc deserialize(JsonObject object, JsonDeserializationContext ctx,
LootItemCondition[] conditions) {
return new PatternScrollFunc(conditions);
return new AddPerWorldPatternToScrollFunc(conditions);
}
}
}

View file

@ -20,14 +20,18 @@ public class AmethystReducerFunc extends LootItemConditionalFunction {
this.delta = delta;
}
@Override
protected ItemStack run(ItemStack stack, LootContext ctx) {
public static ItemStack doStatic(ItemStack stack, LootContext ctx, double amount) {
if (stack.is(Items.AMETHYST_SHARD)) {
stack.setCount((int) (stack.getCount() * (1 + delta)));
stack.setCount((int) (stack.getCount() * (1 + amount)));
}
return stack;
}
@Override
protected ItemStack run(ItemStack stack, LootContext ctx) {
return doStatic(stack, ctx, this.delta);
}
@Override
public LootItemFunctionType getType() {
return HexLootFunctions.AMETHYST_SHARD_REDUCER;

View file

@ -1,73 +1,60 @@
package at.petrak.hexcasting.common.loot;
import at.petrak.hexcasting.api.misc.ScrollQuantity;
import at.petrak.hexcasting.api.mod.HexConfig;
import net.minecraft.Util;
import com.google.common.collect.ImmutableList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
import net.minecraft.world.level.storage.loot.entries.LootTableReference;
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator;
import java.util.EnumMap;
import java.util.List;
import java.util.function.Consumer;
import net.minecraft.util.RandomSource;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
// https://github.com/VazkiiMods/Botania/blob/1.18.x/Xplat/src/main/java/vazkii/botania/common/loot/LootHandler.java
// We need to inject dungeon loot (scrolls and lore), make amethyst drop fewer shards, and the extra dust stuff.
// On forge we do it the "right" way with global loot modifiers; modifiable via a datapack.
// On fabric we do the addition of items by mixing in to loot loading and injecting some loot tables we only generate on
// Fabric as addons, and the subtraction with a loot function. so it's customizable for datapack devs.
// On forge:
// - Scrolls are done with a loot mod
// - Amethyst drop fiddling is done with another loot mod; the shard delta is in the loot mod data and the rest of
// the stuff is loaded from TABLE_INJECT_AMETHYST_CLUSTER
// On fabric:
// - Scrolls are done with a lootLoad listener and the amounts are loaded from config
// - Amethyst shard reduction is done with a loot function mixed in to always be on amethyst clusters, god, cause I
// don't think it's facile to use the loot pool api to try to figure out which pool is for the amethyst and reduce it
// - Amethyst dust and crystals are done by adding the loot table Forge uses in directly via listener
public class HexLootHandler {
// TODO: remove ScrollQuantity, use this class as the source of truth for GLM gen on forge and inject/ loot tables
// on fabric
public static final EnumMap<ScrollQuantity, List<ResourceLocation>> DEFAULT_INJECTS = Util.make(() -> {
var map = new EnumMap<ScrollQuantity, List<ResourceLocation>>(ScrollQuantity.class);
public static final ImmutableList<ScrollInjection> DEFAULT_SCROLL_INJECTS = ImmutableList.of(
// TODO: not sure what the lore implications of scrolls and the nether/end are. adding scrolls
// there for now just to be nice to players.
map.put(ScrollQuantity.FEW, List.of(
new ResourceLocation("minecraft", "chests/jungle_temple"),
new ResourceLocation("minecraft", "chests/simple_dungeon"),
new ResourceLocation("minecraft", "chests/village/village_cartographer")));
map.put(ScrollQuantity.SOME, List.of(
new ResourceLocation("minecraft", "chests/bastion_treasure"),
new ResourceLocation("minecraft", "chests/pillager_outpost"),
new ResourceLocation("minecraft", "chests/shipwreck_map")
));
map.put(ScrollQuantity.MANY, List.of(
// ancient city chests have amethyst in them, thinking emoji
new ResourceLocation("minecraft", "chests/ancient_city"),
new ResourceLocation("minecraft", "chests/stronghold_library")));
// In places where it doesn't really make sense to have them lore-wise just put them rarely anyways
// to make it less of a PITA for new players
new ScrollInjection(new ResourceLocation("minecraft", "chests/simple_dungeon"), 1),
new ScrollInjection(new ResourceLocation("minecraft", "chests/abandoned_mineshaft"), 1),
new ScrollInjection(new ResourceLocation("minecraft", "chests/bastion_other"), 1),
new ScrollInjection(new ResourceLocation("minecraft", "chests/nether_bridge"), 1),
return map;
});
new ScrollInjection(new ResourceLocation("minecraft", "chests/jungle_temple"), 2),
new ScrollInjection(new ResourceLocation("minecraft", "chests/desert_pyramid"), 2),
new ScrollInjection(new ResourceLocation("minecraft", "chests/village/village_cartographer"), 2),
public static final ResourceLocation FUNC_AMETHYST_SHARD_REDUCER = modLoc("amethyst_shard_reducer");
new ScrollInjection(new ResourceLocation("minecraft", "chests/shipwreck_map"), 3),
new ScrollInjection(new ResourceLocation("minecraft", "chests/bastion_treasure"), 3),
new ScrollInjection(new ResourceLocation("minecraft", "chests/end_city_treasure"), 3),
// ancient city chests have amethyst in them, thinking emoji
new ScrollInjection(new ResourceLocation("minecraft", "chests/ancient_city"), 4),
// wonder what those pillagers are up to with those scrolls
new ScrollInjection(new ResourceLocation("minecraft", "chests/pillager_outpost"), 4),
// if you manage to find one of these things you deserve a lot of scrolls
new ScrollInjection(new ResourceLocation("minecraft", "chests/woodland_mansion"), 5),
new ScrollInjection(new ResourceLocation("minecraft", "chests/stronghold_library"), 5)
);
public static int getScrollCount(int range, RandomSource random) {
return Math.max(random.nextIntBetweenInclusive(-range, range), 0);
}
public static final double DEFAULT_SHARD_MODIFICATION = -0.5;
public static final ResourceLocation TABLE_INJECT_AMETHYST_CLUSTER = modLoc("inject/amethyst_cluster");
public static void lootLoad(ResourceLocation id, Consumer<LootPool.Builder> addPool) {
if (id.equals(Blocks.AMETHYST_CLUSTER.getLootTable())) {
addPool.accept(getInjectPool(TABLE_INJECT_AMETHYST_CLUSTER));
} else {
ScrollQuantity scrolls = HexConfig.server().scrollsForLootTable(id);
ResourceLocation injection = scrolls.getPool();
if (injection != null) {
addPool.accept(getInjectPool(injection));
}
}
}
public static LootPool.Builder getInjectPool(ResourceLocation entry) {
return LootPool.lootPool()
.add(getInjectEntry(entry, 1))
.setBonusRolls(UniformGenerator.between(0, 1));
}
private static LootPoolEntryContainer.Builder<?> getInjectEntry(ResourceLocation table, int weight) {
return LootTableReference.lootTableReference(table)
.setWeight(weight);
public record ScrollInjection(ResourceLocation injectee, int countRange) {
}
}

View file

@ -1,11 +1,9 @@
package at.petrak.hexcasting.datagen;
import at.petrak.hexcasting.api.misc.ScrollQuantity;
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.common.loot.PatternScrollFunc;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import at.petrak.paucal.api.datagen.PaucalLootTableProvider;
import net.minecraft.advancements.critereon.EnchantmentPredicate;
@ -35,8 +33,6 @@ import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator;
import java.util.Map;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class HexLootTables extends PaucalLootTableProvider {
public HexLootTables(DataGenerator pGenerator) {
super(pGenerator);
@ -115,17 +111,6 @@ public class HexLootTables extends PaucalLootTableProvider {
.withPool(dustPoolWhenBad)
.withPool(isThatAnMFingBrandonSandersonReference)
.withPool(isThatAnMFingBadBrandonSandersonReference));
String[] rarities = new String[]{
"few",
"some",
"many"
};
for (int i = 0; i < rarities.length; i++) {
var quantity = ScrollQuantity.values()[i + 1];
var scrollPool = makeScrollAdder(quantity.countRange);
lootTables.put(modLoc("inject/scroll_loot_" + rarities[i]), scrollPool);
}
}
private void makeLeafTable(Map<Block, LootTable.Builder> lootTables, Block block) {
@ -147,13 +132,4 @@ public class HexLootTables extends PaucalLootTableProvider {
.apply(ApplyExplosionDecay.explosionDecay());
lootTables.put(block, LootTable.lootTable().withPool(leafPool));
}
// "stddev"
private LootTable.Builder makeScrollAdder(float stddev) {
var pool = LootPool.lootPool()
.setRolls(UniformGenerator.between(-stddev, stddev))
.add(LootItem.lootTableItem(HexItems.SCROLL_LARGE))
.apply(() -> new PatternScrollFunc(new LootItemCondition[0]));
return LootTable.lootTable().withPool(pool);
}
}

View file

@ -174,10 +174,12 @@
"emi.category.hexcasting.villager_leveling": "Trade Leveling",
"emi.category.hexcasting.villager_profession": "Villager Profession",
"text.autoconfig.hexcasting.title": "Hexcasting Config",
"text.autoconfig.hexcasting.category.common": "Common",
"text.autoconfig.hexcasting.category.client": "Client",
"text.autoconfig.hexcasting.category.server": "Server",
"text.autoconfig.hexcasting.option.common.dustMediaAmount": "Dust Media Amount",
"text.autoconfig.hexcasting.option.common.shardMediaAmount": "Shard Media Amount",
"text.autoconfig.hexcasting.option.common.chargedCrystalMediaAmount": "Charged Crystal Media Amount",
@ -186,6 +188,7 @@
"text.autoconfig.hexcasting.option.common.shardMediaAmount.@Tooltip": "How much media a single Amethyst Shard item is worth",
"text.autoconfig.hexcasting.option.common.chargedCrystalMediaAmount.@Tooltip": "How much media a single Charged Amethyst Crystal item is worth",
"text.autoconfig.hexcasting.option.common.mediaToHealthRate.@Tooltip": "How many points of media a half-heart is worth when casting from HP",
"text.autoconfig.hexcasting.option.client.ctrlTogglesOffStrokeOrder": "Ctrl Toggles Off Stroke Order",
"text.autoconfig.hexcasting.option.client.invertSpellbookScrollDirection": "Invert Spellbook Scroll Direction",
"text.autoconfig.hexcasting.option.client.invertAbacusScrollDirection": "Invert Abacus Scroll Direction",
@ -194,15 +197,15 @@
"text.autoconfig.hexcasting.option.client.invertSpellbookScrollDirection.@Tooltip": "Whether scrolling up (as opposed to down) will increase the page index of the spellbook, and vice versa",
"text.autoconfig.hexcasting.option.client.invertAbacusScrollDirection.@Tooltip": "Whether scrolling up (as opposed to down) will increase the page index of the abacus, and vice versa",
"text.autoconfig.hexcasting.option.client.gridSnapThreshold.@Tooltip": "When using a staff, the distance from one dot you have to go to snap to the next dot, where 0.5 means 50% of the way (0.5-1)",
"text.autoconfig.hexcasting.option.server.opBreakHarvestLevel": "Break Harvest Level",
"text.autoconfig.hexcasting.option.server.maxRecurseDepth": "Max Recurse Depth",
"text.autoconfig.hexcasting.option.server.maxSpellCircleLength": "Max Spell Circle Length",
"text.autoconfig.hexcasting.option.server.actionDenyList": "Action Deny List",
"text.autoconfig.hexcasting.option.server.circleActionDenyList": "Circle Action Deny List",
"text.autoconfig.hexcasting.option.server.villagersOffendedByMindMurder": "Villagers Offended By Mind Murder",
"text.autoconfig.hexcasting.option.server.fewScrollTables": "Few Scroll Tables",
"text.autoconfig.hexcasting.option.server.someScrollTables": "Some Scroll Tables",
"text.autoconfig.hexcasting.option.server.manyScrollTables": "Many Scroll Tables",
"text.autoconfig.hexcasting.option.server.scrollInjectionsRaw": "Scroll Injection Weights",
"text.autoconfig.hexcasting.option.server.amethystShardModification": "Amethyst Shard Drop Rate Change",
"text.autoconfig.hexcasting.option.server.opBreakHarvestLevel.@Tooltip": "The harvest level of the Break Block spell.\n0 = wood, 1 = stone, 2 = iron, 3 = diamond, 4 = netherite.",
"text.autoconfig.hexcasting.option.server.maxRecurseDepth.@Tooltip": "How many times an action can recursively cast other actions",
"text.autoconfig.hexcasting.option.server.maxSpellCircleLength.@Tooltip": "The maximum number of slates in a spell circle",
@ -212,6 +215,8 @@
"text.autoconfig.hexcasting.option.server.fewScrollTables.@Tooltip": "Loot tables that a small number of Ancient Scrolls are injected into",
"text.autoconfig.hexcasting.option.server.someScrollTables.@Tooltip": "Loot tables that a decent number of Ancient Scrolls are injected into",
"text.autoconfig.hexcasting.option.server.manyScrollTables.@Tooltip": "Loot tables that a huge number of Ancient Scrolls are injected into",
"text.autoconfig.hexcasting.option.server.scrollInjectionsRaw.@Tooltip": "Maps the names of loot tables to the amount of per-world patterns on scrolls should go in them. There's about a 50% chance to get any scrolls in a given chest marked here; once that is met, between 1 and that many scrolls are generated.",
"text.autoconfig.hexcasting.option.server.amethystShardModification.@Tooltip": "How much the number of amethyst shards dropped from clusters is increased/decreased.",
"advancement.hexcasting:root": "Hexcasting Research",

View file

@ -8,7 +8,6 @@
"MixinAbstractVillager",
"MixinMob",
"MixinRaider",
"MixinReloadableServerResources",
"MixinVillager",
"MixinWitch",
"accessor.AccessorEntity",

View file

@ -1,4 +1,4 @@
// 1.19.2 2023-01-22T20:54:31.1145534 Tags for minecraft:item
// 1.19.2 2023-01-22T23:57:23.050599591 Tags for minecraft:item
5928bad07d3872bb60f29ef4f3c885c8e1967c20 data/hexcasting/tags/items/phial_base.json
fdb48f194d7937ab6b423fa4b90a4d438bf6dd90 data/minecraft/tags/items/wooden_doors.json
e5df19a1dc6eadf14cd9b0f0fe45a74330b745e9 data/hexcasting/tags/items/edified_planks.json

View file

@ -1,5 +1,4 @@
// 1.19.2 2023-01-22T20:54:31.115936247 LootTables
01a50f557196c705c275722015cf893e0abe6425 data/hexcasting/loot_tables/inject/scroll_loot_many.json
// 1.19.2 2023-01-22T23:57:23.070700759 LootTables
dec1d3592e82f99d9e059d9c771530f103b2bda5 data/hexcasting/loot_tables/blocks/empty_directrix.json
2c42fc5d8c74c98ad15b8bd50f56541fccbef750 data/hexcasting/loot_tables/blocks/edified_tile.json
cfb39e2151725fe4f9a7269d9b5de8031ea54a44 data/hexcasting/loot_tables/blocks/directrix_redstone.json
@ -15,7 +14,6 @@ a3ca7f9427bd57a6033f241754d49425251cc091 data/hexcasting/loot_tables/blocks/scro
201bbf7adff979ff8cb087e1798da5a2a31eed09 data/hexcasting/loot_tables/blocks/akashic_connector.json
ac9d01324ffe7c1ea963aa7def5c177db820067f data/hexcasting/loot_tables/blocks/amethyst_tiles.json
e329c8ad61d61ad9be91d6ab4c36d57c05990e0c data/hexcasting/loot_tables/blocks/amethyst_dust_block.json
a7a08d76b8a1b1596a0d67d422d7a0d93f3a1d2f data/hexcasting/loot_tables/inject/scroll_loot_few.json
3b1e2f738c4906371a4cdecf24253ad94ae66320 data/hexcasting/loot_tables/blocks/akashic_bookshelf.json
5da5b504c400c052ee8b03cf88e78dc567456ef8 data/hexcasting/loot_tables/blocks/amethyst_sconce.json
d21fdf6326f7a9958df22224e5e34489d63e013d data/hexcasting/loot_tables/blocks/edified_door.json
@ -36,4 +34,3 @@ b7f7af68760b51d0c438f5c6039f1cd7157fa452 data/hexcasting/loot_tables/blocks/anci
9ee4259b51cccd4582fb2e52ab9f64e92af857bb data/hexcasting/loot_tables/blocks/edified_log.json
c089d3d230ae5354f2a9953f65bba77b6e26d976 data/hexcasting/loot_tables/blocks/edified_trapdoor.json
745b510161cfff804b115f566ad6b50e0cb492d1 data/hexcasting/loot_tables/blocks/slate.json
fd874549344d85ec2bb6edcb7fe7af62cafebba2 data/hexcasting/loot_tables/inject/scroll_loot_some.json

View file

@ -1,4 +1,4 @@
// 1.19.2 2023-01-22T20:54:31.115320251 Tags for minecraft:block
// 1.19.2 2023-01-22T23:57:23.071366626 Tags for minecraft:block
20183cd61968ff6548df2dde1100b6378d68d64b data/minecraft/tags/blocks/wooden_buttons.json
357eddf3cee6f16725bed0701d57b2ca3097d74d data/minecraft/tags/blocks/mineable/shovel.json
5216ba5c57db29b8dee9aebc63a2e3b17c97dc17 data/minecraft/tags/blocks/wooden_trapdoors.json

View file

@ -1,4 +1,4 @@
// 1.19.2 2023-01-22T20:54:31.092846061 Tags for hexcasting:action
// 1.19.2 2023-01-22T23:57:23.069878587 Tags for hexcasting:action
e5afc567ea17f035e4eb1d1d48825100b7f6ad68 data/hexcasting/tags/action/per_world_pattern.json
e5afc567ea17f035e4eb1d1d48825100b7f6ad68 data/hexcasting/tags/action/requires_enlightenment.json
e5afc567ea17f035e4eb1d1d48825100b7f6ad68 data/hexcasting/tags/action/can_start_enlighten.json

View file

@ -1,4 +1,4 @@
// 1.19.2 2023-01-22T20:54:31.094256565 Recipes
// 1.19.2 2023-01-22T23:57:23.052460583 Recipes
9f75d3e93ecbbbf3ed9a92b2943397e09dcae1a9 data/hexcasting/recipes/dye_colorizer_light_blue.json
04569ccadfd99f203b0485d0c3e877209290f2b3 data/hexcasting/advancements/recipes/hexcasting.creative_tab/dye_colorizer_pink.json
2a9d4a0f3618abf9e9b8699b318a984d2c836913 data/hexcasting/advancements/recipes/brainsweep/brainsweep/directrix_redstone.json

View file

@ -1,23 +0,0 @@
{
"pools": [
{
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:scroll"
}
],
"functions": [
{
"function": "hexcasting:pattern_scroll"
}
],
"rolls": {
"type": "minecraft:uniform",
"max": 1.0,
"min": -1.0
}
}
]
}

View file

@ -1,23 +0,0 @@
{
"pools": [
{
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:scroll"
}
],
"functions": [
{
"function": "hexcasting:pattern_scroll"
}
],
"rolls": {
"type": "minecraft:uniform",
"max": 3.0,
"min": -3.0
}
}
]
}

View file

@ -1,23 +0,0 @@
{
"pools": [
{
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:scroll"
}
],
"functions": [
{
"function": "hexcasting:pattern_scroll"
}
],
"rolls": {
"type": "minecraft:uniform",
"max": 2.0,
"min": -2.0
}
}
]
}

View file

@ -1,9 +1,11 @@
package at.petrak.hexcasting.fabric;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.misc.ScrollQuantity;
import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.annotation.Config;
@ -17,7 +19,6 @@ import net.minecraft.world.level.Level;
import java.util.List;
import static at.petrak.hexcasting.api.mod.HexConfig.anyMatch;
import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch;
@Config(name = HexAPI.MOD_ID)
@ -27,15 +28,15 @@ import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch;
public class FabricHexConfig extends PartitioningSerializer.GlobalData {
@ConfigEntry.Category("common")
@ConfigEntry.Gui.TransitiveObject
private final Common common = new Common();
public final Common common = new Common();
@ConfigEntry.Category("client")
@ConfigEntry.Gui.TransitiveObject
private final Client client = new Client();
public final Client client = new Client();
@ConfigEntry.Category("server")
@ConfigEntry.Gui.TransitiveObject
private final Server server = new Server();
public final Server server = new Server();
public static void setup() {
public static FabricHexConfig setup() {
AutoConfig.register(FabricHexConfig.class, PartitioningSerializer.wrap(JanksonConfigSerializer::new));
var instance = AutoConfig.getConfigHolder(FabricHexConfig.class).getConfig();
@ -47,10 +48,12 @@ public class FabricHexConfig extends PartitioningSerializer.GlobalData {
// but we care about the server on the *logical* server
// i believe this should Just Work without a guard? assuming we don't access it from the client ever
HexConfig.setServer(instance.server);
return instance;
}
@Config(name = "common")
private static final class Common implements HexConfig.CommonConfigAccess, ConfigData {
public static final class Common implements HexConfig.CommonConfigAccess, ConfigData {
@ConfigEntry.Gui.Tooltip
private int dustMediaAmount = DEFAULT_DUST_MEDIA_AMOUNT;
@ConfigEntry.Gui.Tooltip
@ -90,7 +93,7 @@ public class FabricHexConfig extends PartitioningSerializer.GlobalData {
}
@Config(name = "client")
private static final class Client implements HexConfig.ClientConfigAccess, ConfigData {
public static final class Client implements HexConfig.ClientConfigAccess, ConfigData {
@ConfigEntry.Gui.Tooltip
private boolean ctrlTogglesOffStrokeOrder = DEFAULT_CTRL_TOGGLES_OFF_STROKE_ORDER;
@ConfigEntry.Gui.Tooltip
@ -127,7 +130,7 @@ public class FabricHexConfig extends PartitioningSerializer.GlobalData {
}
@Config(name = "server")
private static final class Server implements HexConfig.ServerConfigAccess, ConfigData {
public static final class Server implements HexConfig.ServerConfigAccess, ConfigData {
@ConfigEntry.BoundedDiscrete(min = 0, max = 4)
@ConfigEntry.Gui.Tooltip
private int opBreakHarvestLevel = DEFAULT_OP_BREAK_HARVEST_LEVEL;
@ -146,16 +149,22 @@ public class FabricHexConfig extends PartitioningSerializer.GlobalData {
private List<String> tpDimDenylist = DEFAULT_DIM_TP_DENYLIST;
@ConfigEntry.Gui.Tooltip
private List<String> fewScrollTables = DEFAULT_FEW_SCROLL_TABLES;
@ConfigEntry.Gui.Tooltip
private List<String> someScrollTables = DEFAULT_SOME_SCROLL_TABLES;
@ConfigEntry.Gui.Tooltip
private List<String> manyScrollTables = DEFAULT_MANY_SCROLL_TABLES;
private List<ScrollInjectionMirror> scrollInjectionsRaw = HexLootHandler.DEFAULT_SCROLL_INJECTS
.stream()
.map(si -> new ScrollInjectionMirror(si.injectee(), si.countRange()))
.toList();
@ConfigEntry.Gui.Excluded
private transient Object2IntMap<ResourceLocation> scrollInjections;
@Override
public void validatePostLoad() throws ValidationException {
this.maxRecurseDepth = Math.max(this.maxRecurseDepth, 0);
this.maxSpellCircleLength = Math.max(this.maxSpellCircleLength, 4);
this.scrollInjections = new Object2IntOpenHashMap<>();
for (var mirror : this.scrollInjectionsRaw) {
this.scrollInjections.put(mirror.injectee(), mirror.countRange());
}
}
@Override
@ -190,19 +199,17 @@ public class FabricHexConfig extends PartitioningSerializer.GlobalData {
@Override
public boolean canTeleportInThisDimension(ResourceKey<Level> dimension) {
return noneMatch(manyScrollTables, dimension.location());
return noneMatch(tpDimDenylist, dimension.location());
}
@Override
public ScrollQuantity scrollsForLootTable(ResourceLocation lootTable) {
if (anyMatch(fewScrollTables, lootTable)) {
return ScrollQuantity.FEW;
} else if (anyMatch(someScrollTables, lootTable)) {
return ScrollQuantity.SOME;
} else if (anyMatch(manyScrollTables, lootTable)) {
return ScrollQuantity.MANY;
}
return ScrollQuantity.NONE;
/**
* Returns -1 if none is found
*/
public int scrollRangeForLootTable(ResourceLocation lootTable) {
return this.scrollInjections.getOrDefault(lootTable, -1);
}
record ScrollInjectionMirror(ResourceLocation injectee, int countRange) {
}
}
}

View file

@ -19,7 +19,6 @@ import at.petrak.hexcasting.common.lib.hex.HexActions
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes
import at.petrak.hexcasting.common.lib.hex.HexSpecialHandlers
import at.petrak.hexcasting.common.loot.HexLootHandler
import at.petrak.hexcasting.common.misc.AkashicTreeGrower
import at.petrak.hexcasting.common.misc.BrainsweepingEvents
import at.petrak.hexcasting.common.misc.PlayerPositionRecorder
@ -28,6 +27,7 @@ import at.petrak.hexcasting.fabric.event.VillagerConversionCallback
import at.petrak.hexcasting.fabric.interop.gravity.GravityApiInterop
import at.petrak.hexcasting.fabric.interop.gravity.OpChangeGravity
import at.petrak.hexcasting.fabric.interop.gravity.OpGetGravity
import at.petrak.hexcasting.fabric.loot.FabricHexLootModJankery
import at.petrak.hexcasting.fabric.network.FabricPacketHandler
import at.petrak.hexcasting.fabric.recipe.FabricModConditionalIngredient
import at.petrak.hexcasting.fabric.storage.FabricImpetusStorage
@ -50,8 +50,10 @@ import net.minecraft.world.InteractionResult
import java.util.function.BiConsumer
object FabricHexInitializer : ModInitializer {
public lateinit var CONFIG: FabricHexConfig
override fun onInitialize() {
FabricHexConfig.setup()
this.CONFIG = FabricHexConfig.setup()
FabricPacketHandler.init()
initListeners()
@ -96,10 +98,8 @@ object FabricHexInitializer : ModInitializer {
CommandRegistrationCallback.EVENT.register { dp, _, _ -> HexCommands.register(dp) }
LootTableEvents.MODIFY.register { _, _, id, supplier, _ ->
HexLootHandler.lootLoad(id, supplier::withPool)
FabricHexLootModJankery.lootLoad(id, supplier::withPool)
}
}
private fun initRegistries() {

View file

@ -0,0 +1,46 @@
package at.petrak.hexcasting.fabric.loot;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.loot.AddPerWorldPatternToScrollFunc;
import at.petrak.hexcasting.fabric.FabricHexInitializer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.entries.LootItem;
import net.minecraft.world.level.storage.loot.entries.LootTableReference;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
import static at.petrak.hexcasting.common.loot.HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER;
public class FabricHexLootModJankery {
public static final ResourceLocation FUNC_AMETHYST_SHARD_REDUCER = modLoc("amethyst_shard_reducer");
public static void lootLoad(ResourceLocation id, Consumer<LootPool.Builder> addPool) {
if (id.equals(Blocks.AMETHYST_CLUSTER.getLootTable())) {
addPool.accept(makeAmethystInjectPool());
} else {
int countRange = FabricHexInitializer.CONFIG.server.scrollRangeForLootTable(id);
if (countRange != -1) {
addPool.accept(makeScrollAddPool(countRange));
}
}
}
@NotNull
private static LootPool.Builder makeAmethystInjectPool() {
return LootPool.lootPool()
.add(LootTableReference.lootTableReference(TABLE_INJECT_AMETHYST_CLUSTER));
}
private static LootPool.Builder makeScrollAddPool(int range) {
return LootPool.lootPool()
.setRolls(UniformGenerator.between(-range, range))
.add(LootItem.lootTableItem(HexItems.SCROLL_LARGE))
.apply(() -> new AddPerWorldPatternToScrollFunc(new LootItemCondition[0]));
}
}

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.mixin;
package at.petrak.hexcasting.fabric.mixin;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.fabric.loot.FabricHexLootModJankery;
import at.petrak.hexcasting.mixin.accessor.AccessorLootTable;
import net.minecraft.server.ReloadableServerResources;
import net.minecraft.world.level.block.Blocks;
@ -15,7 +15,8 @@ import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
@Mixin(ReloadableServerResources.class)
public class MixinReloadableServerResources {
public class FabricMixinReloadableServerResources {
// Add the amethyst shard
@Inject(method = "loadResources", at = @At("RETURN"), cancellable = true)
private static void onLoadResources(CallbackInfoReturnable<CompletableFuture<ReloadableServerResources>> cir) {
cir.setReturnValue(cir.getReturnValue().thenApply((rsr) -> {
@ -23,13 +24,13 @@ public class MixinReloadableServerResources {
var theCoolerAmethystTable = (AccessorLootTable) amethystTable;
var oldFuncs = theCoolerAmethystTable.hex$getFunctions();
var newFuncs = Arrays.copyOf(oldFuncs, oldFuncs.length + 1);
var shardReducer = rsr.getItemModifierManager().get(HexLootHandler.FUNC_AMETHYST_SHARD_REDUCER);
var shardReducer = rsr.getItemModifierManager().get(FabricHexLootModJankery.FUNC_AMETHYST_SHARD_REDUCER);
if (shardReducer != null) {
newFuncs[newFuncs.length - 1] = shardReducer;
theCoolerAmethystTable.hex$setFunctions(newFuncs);
theCoolerAmethystTable.hex$setCompositeFunction(LootItemFunctions.compose(newFuncs));
} else {
HexAPI.LOGGER.warn("{} was not found?", HexLootHandler.FUNC_AMETHYST_SHARD_REDUCER);
HexAPI.LOGGER.warn("{} was not found?", FabricHexLootModJankery.FUNC_AMETHYST_SHARD_REDUCER);
}
return rsr;
}));

View file

@ -10,8 +10,9 @@
"FabricEnchantmentTableBlockMixin",
"FabricItemEntityMixin",
"FabricLivingEntityMixin",
"FabricVillagerTurnIntoWitchMixin",
"FabricMobMixin"
"FabricMixinReloadableServerResources",
"FabricMobMixin",
"FabricVillagerTurnIntoWitchMixin"
],
"client": [
"client.FabricAbstractTextureMixin",

View file

@ -1,4 +1,4 @@
// 1.19.2 2022-11-04T11:52:25.2422393 LootTables
// 1.19.2 2023-01-22T23:58:04.863036007 LootTables
3b1e2f738c4906371a4cdecf24253ad94ae66320 data/hexcasting/loot_tables/blocks/akashic_bookshelf.json
201bbf7adff979ff8cb087e1798da5a2a31eed09 data/hexcasting/loot_tables/blocks/akashic_connector.json
16498092b43c43a4a7617ba91bcfcc13b87d9a7e data/hexcasting/loot_tables/blocks/akashic_record.json
@ -34,6 +34,3 @@ a3ca7f9427bd57a6033f241754d49425251cc091 data/hexcasting/loot_tables/blocks/scro
457b355c6a5e1b2ee4ddda37a39084ceef3546d7 data/hexcasting/loot_tables/blocks/stripped_edified_log.json
6e4bc6364e7e1cc97f1ad1127608a0b95e4d156f data/hexcasting/loot_tables/blocks/stripped_edified_wood.json
e17ca4b3e84c4fb6dadfee273e6040cf15724014 data/hexcasting/loot_tables/inject/amethyst_cluster.json
a7a08d76b8a1b1596a0d67d422d7a0d93f3a1d2f data/hexcasting/loot_tables/inject/scroll_loot_few.json
01a50f557196c705c275722015cf893e0abe6425 data/hexcasting/loot_tables/inject/scroll_loot_many.json
fd874549344d85ec2bb6edcb7fe7af62cafebba2 data/hexcasting/loot_tables/inject/scroll_loot_some.json

View file

@ -0,0 +1,17 @@
// 1.19.2 2023-01-22T23:58:04.861380072 Global Loot Modifiers : hexcasting
bdfa7329fd17b9128e2bc03c662682e434d74c29 data/forge/loot_modifiers/global_loot_modifiers.json
28ca895a27221312c2451f26646111a68aadbf6c data/hexcasting/loot_modifiers/amethyst_cluster.json
a89a9e3113b83c6eb978f101aad42a6b37e7c1d8 data/hexcasting/loot_modifiers/scroll/minecraft/chests/abandoned_mineshaft.json
bfac0ff9e84cd974ccfb47edc9dce78476470103 data/hexcasting/loot_modifiers/scroll/minecraft/chests/ancient_city.json
0fcb299789a1b0162ab81a025a06b1aab5eb504b data/hexcasting/loot_modifiers/scroll/minecraft/chests/bastion_other.json
11bcc55690e58fdf2268cbb47e343efe5b806900 data/hexcasting/loot_modifiers/scroll/minecraft/chests/bastion_treasure.json
664640cdc4aad746e95354812a23724452d00717 data/hexcasting/loot_modifiers/scroll/minecraft/chests/desert_pyramid.json
2d309086694294c3da3056391adc50624ac91ba7 data/hexcasting/loot_modifiers/scroll/minecraft/chests/end_city_treasure.json
83097d0aa55dbbd8a3c520445b555ce2d10d8635 data/hexcasting/loot_modifiers/scroll/minecraft/chests/jungle_temple.json
787b9439a8c66e76487b157b42722c17a9911502 data/hexcasting/loot_modifiers/scroll/minecraft/chests/nether_bridge.json
489e7f900012fd155416420ce0bb557e661dac61 data/hexcasting/loot_modifiers/scroll/minecraft/chests/pillager_outpost.json
688ceb7b895290d939701961ac8a8eeea4199e3a data/hexcasting/loot_modifiers/scroll/minecraft/chests/shipwreck_map.json
992bd485599c5ae83b89b2456beda648b8c463b5 data/hexcasting/loot_modifiers/scroll/minecraft/chests/simple_dungeon.json
22d2938c6e71e5aec42b4c0b98d5856255f362eb data/hexcasting/loot_modifiers/scroll/minecraft/chests/stronghold_library.json
30c828238be60878805070d8d9322672dfc2f1d9 data/hexcasting/loot_modifiers/scroll/minecraft/chests/village/village_cartographer.json
c8d296e8d470ac101c3a719b235ea9b09ce0b655 data/hexcasting/loot_modifiers/scroll/minecraft/chests/woodland_mansion.json

View file

@ -0,0 +1,20 @@
{
"entries": [
"hexcasting:scroll/minecraft/chests/bastion_other",
"hexcasting:scroll/minecraft/chests/nether_bridge",
"hexcasting:scroll/minecraft/chests/village/village_cartographer",
"hexcasting:scroll/minecraft/chests/end_city_treasure",
"hexcasting:scroll/minecraft/chests/jungle_temple",
"hexcasting:scroll/minecraft/chests/bastion_treasure",
"hexcasting:scroll/minecraft/chests/pillager_outpost",
"hexcasting:scroll/minecraft/chests/desert_pyramid",
"hexcasting:scroll/minecraft/chests/shipwreck_map",
"hexcasting:scroll/minecraft/chests/abandoned_mineshaft",
"hexcasting:amethyst_cluster",
"hexcasting:scroll/minecraft/chests/ancient_city",
"hexcasting:scroll/minecraft/chests/stronghold_library",
"hexcasting:scroll/minecraft/chests/woodland_mansion",
"hexcasting:scroll/minecraft/chests/simple_dungeon"
],
"replace": false
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:amethyst_cluster",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:blocks/amethyst_cluster"
}
],
"shardDelta": -0.5
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/abandoned_mineshaft"
}
],
"countRange": 1
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/ancient_city"
}
],
"countRange": 4
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_other"
}
],
"countRange": 1
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/bastion_treasure"
}
],
"countRange": 3
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/desert_pyramid"
}
],
"countRange": 2
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/end_city_treasure"
}
],
"countRange": 3
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/jungle_temple"
}
],
"countRange": 2
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/nether_bridge"
}
],
"countRange": 1
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/pillager_outpost"
}
],
"countRange": 4
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/shipwreck_map"
}
],
"countRange": 3
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/simple_dungeon"
}
],
"countRange": 1
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/stronghold_library"
}
],
"countRange": 5
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/village/village_cartographer"
}
],
"countRange": 2
}

View file

@ -0,0 +1,10 @@
{
"type": "hexcasting:inject_scrolls",
"conditions": [
{
"condition": "forge:loot_table_id",
"loot_table_id": "minecraft:chests/woodland_mansion"
}
],
"countRange": 5
}

View file

@ -1,23 +0,0 @@
{
"pools": [
{
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:scroll"
}
],
"functions": [
{
"function": "hexcasting:pattern_scroll"
}
],
"rolls": {
"type": "minecraft:uniform",
"max": 1.0,
"min": -1.0
}
}
]
}

View file

@ -1,23 +0,0 @@
{
"pools": [
{
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:scroll"
}
],
"functions": [
{
"function": "hexcasting:pattern_scroll"
}
],
"rolls": {
"type": "minecraft:uniform",
"max": 3.0,
"min": -3.0
}
}
]
}

View file

@ -1,23 +0,0 @@
{
"pools": [
{
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "hexcasting:scroll"
}
],
"functions": [
{
"function": "hexcasting:pattern_scroll"
}
],
"rolls": {
"type": "minecraft:uniform",
"max": 2.0,
"min": -2.0
}
}
]
}

View file

@ -1,6 +1,5 @@
package at.petrak.hexcasting.forge;
import at.petrak.hexcasting.api.misc.ScrollQuantity;
import at.petrak.hexcasting.api.mod.HexConfig;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
@ -9,7 +8,6 @@ import net.minecraftforge.common.ForgeConfigSpec;
import java.util.List;
import static at.petrak.hexcasting.api.mod.HexConfig.anyMatch;
import static at.petrak.hexcasting.api.mod.HexConfig.noneMatch;
public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
@ -143,18 +141,6 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
tpDimDenyList = builder.comment("Resource locations of dimensions you can't Blink or Greater Teleport in.")
.defineList("tpDimDenyList", DEFAULT_DIM_TP_DENYLIST, Server::isValidReslocArg);
builder.push("Scrolls in Loot");
fewScrollTables = builder.comment(
"Which loot tables should a small number of Ancient Scrolls be injected into?")
.defineList("fewScrollTables", DEFAULT_FEW_SCROLL_TABLES, Server::isValidReslocArg);
someScrollTables = builder.comment(
"Which loot tables should a decent number of Ancient Scrolls be injected into?")
.defineList("someScrollTables", DEFAULT_SOME_SCROLL_TABLES, Server::isValidReslocArg);
manyScrollTables = builder.comment(
"Which loot tables should a huge number of Ancient Scrolls be injected into?")
.defineList("manyScrollTables", DEFAULT_MANY_SCROLL_TABLES, Server::isValidReslocArg);
}
@Override
@ -192,32 +178,6 @@ public class ForgeHexConfig implements HexConfig.CommonConfigAccess {
return noneMatch(tpDimDenyList.get(), dimension.location());
}
// TODO: on Forge, this value isn't loaded when creating a new world yet because config is per-world.
// For now I'm hardcoding this, but for correctness we should probably switch the table
// injects to be loaded from datapack instead of config.
// (Without hardcoding loading a new world is *incredibly* laggy because it throws every single time it tries to
// load *any* loot table)
@Override
public ScrollQuantity scrollsForLootTable(ResourceLocation lootTable) {
try {
if (anyMatch(HexConfig.ServerConfigAccess.DEFAULT_FEW_SCROLL_TABLES, lootTable)) {
return ScrollQuantity.FEW;
} else if (anyMatch(HexConfig.ServerConfigAccess.DEFAULT_SOME_SCROLL_TABLES, lootTable)) {
return ScrollQuantity.SOME;
} else if (anyMatch(HexConfig.ServerConfigAccess.DEFAULT_MANY_SCROLL_TABLES, lootTable)) {
return ScrollQuantity.MANY;
}
} catch (IllegalStateException ignored) {
// then we are in develop env AND this is being called in the new world screen (it loads datapacks for
// world generation options)
// config values don't exist yet because config is per-world on Forge, and in dev it throws an exn
// (in release it just silently returns default, which is expected behavior here, but the comment
// suggests
// it will start throwing at some point soon.)
}
return ScrollQuantity.NONE;
}
private static boolean isValidReslocArg(Object o) {
return o instanceof String s && ResourceLocation.isValidResourceLocation(s);
}

View file

@ -16,14 +16,13 @@ import at.petrak.hexcasting.common.lib.hex.HexActions;
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import at.petrak.hexcasting.common.lib.hex.HexSpecialHandlers;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.common.misc.AkashicTreeGrower;
import at.petrak.hexcasting.common.misc.BrainsweepingEvents;
import at.petrak.hexcasting.common.misc.PlayerPositionRecorder;
import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry;
import at.petrak.hexcasting.forge.cap.CapSyncers;
import at.petrak.hexcasting.forge.cap.ForgeCapabilityHandler;
import at.petrak.hexcasting.forge.datagen.HexForgeDataGenerators;
import at.petrak.hexcasting.forge.datagen.ForgeHexDataGenerators;
import at.petrak.hexcasting.forge.interop.curios.CuriosApiInterop;
import at.petrak.hexcasting.forge.interop.curios.CuriosRenderers;
import at.petrak.hexcasting.forge.lib.ForgeHexArgumentTypeRegistry;
@ -49,7 +48,6 @@ import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.ToolActions;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.event.LootTableLoadEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.living.LivingConversionEvent;
@ -201,10 +199,6 @@ public class ForgeHexInitializer {
evt.setCanceled(ItemJewelerHammer.shouldFailToBreak(evt.getEntity(), evt.getState(), pos.get()));
});
evBus.addListener((LootTableLoadEvent evt) -> HexLootHandler.lootLoad(
evt.getName(),
builder -> evt.getTable().addPool(builder.build())));
// === Events implemented in other ways on Fabric
// On Fabric this should be auto-synced
@ -234,7 +228,7 @@ public class ForgeHexInitializer {
evBus.addGenericListener(BlockEntity.class, ForgeCapabilityHandler::attachBlockEntityCaps);
evBus.addGenericListener(Entity.class, ForgeCapabilityHandler::attachEntityCaps);
modBus.register(HexForgeDataGenerators.class);
modBus.register(ForgeHexDataGenerators.class);
modBus.register(ForgeCapabilityHandler.class);
evBus.register(CapSyncers.class);

View file

@ -16,11 +16,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class HexForgeConditionsBuilder implements IXplatConditionsBuilder, IConditionBuilder {
public class ForgeHexConditionsBuilder implements IXplatConditionsBuilder, IConditionBuilder {
private final List<ICondition> conditions = new ArrayList<>();
private final RecipeBuilder parent;
public HexForgeConditionsBuilder(RecipeBuilder parent) {
public ForgeHexConditionsBuilder(RecipeBuilder parent) {
this.parent = parent;
}
@ -37,7 +37,8 @@ public class HexForgeConditionsBuilder implements IXplatConditionsBuilder, ICond
}
@Override
public @NotNull RecipeBuilder unlockedBy(@NotNull String string, @NotNull CriterionTriggerInstance criterionTriggerInstance) {
public @NotNull RecipeBuilder unlockedBy(@NotNull String string,
@NotNull CriterionTriggerInstance criterionTriggerInstance) {
return parent.unlockedBy(string, criterionTriggerInstance);
}

View file

@ -31,7 +31,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
import java.util.EnumMap;
import java.util.stream.Stream;
public class HexForgeDataGenerators {
public class ForgeHexDataGenerators {
@SubscribeEvent
public static void generateData(GatherDataEvent ev) {
if (System.getProperty("hexcasting.xplat_datagen") != null) {
@ -59,7 +59,7 @@ public class HexForgeDataGenerators {
DataGenerator gen = ev.getGenerator();
ExistingFileHelper efh = ev.getExistingFileHelper();
gen.addProvider(ev.includeServer(), new HexLootTables(gen));
gen.addProvider(ev.includeServer(), new HexplatRecipes(gen, INGREDIENTS, HexForgeConditionsBuilder::new));
gen.addProvider(ev.includeServer(), new HexplatRecipes(gen, INGREDIENTS, ForgeHexConditionsBuilder::new));
var xtags = IXplatAbstractions.INSTANCE.tags();
var blockTagProvider = PaucalForgeDatagenWrappers.addEFHToTagProvider(
@ -70,6 +70,8 @@ public class HexForgeDataGenerators {
gen.addProvider(ev.includeServer(), itemTagProvider);
gen.addProvider(ev.includeServer(),
PaucalForgeDatagenWrappers.addEFHToTagProvider(new HexActionTagProvider(gen), efh));
gen.addProvider(ev.includeServer(), new ForgeHexLootModGen(gen));
}
private static final IXplatIngredients INGREDIENTS = new IXplatIngredients() {

View file

@ -0,0 +1,31 @@
package at.petrak.hexcasting.forge.datagen;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.forge.loot.ForgeHexAmethystLootMod;
import at.petrak.hexcasting.forge.loot.ForgeHexScrollLootMod;
import net.minecraft.data.DataGenerator;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraftforge.common.data.GlobalLootModifierProvider;
import net.minecraftforge.common.loot.LootTableIdCondition;
public class ForgeHexLootModGen extends GlobalLootModifierProvider {
public ForgeHexLootModGen(DataGenerator gen) {
super(gen, HexAPI.MOD_ID);
}
@Override
protected void start() {
for (var injection : HexLootHandler.DEFAULT_SCROLL_INJECTS) {
var name = "scroll/%s/%s".formatted(injection.injectee().getNamespace(), injection.injectee().getPath());
add(name, new ForgeHexScrollLootMod(new LootItemCondition[]{
LootTableIdCondition.builder(injection.injectee()).build(),
}, injection.countRange()));
}
add("amethyst_cluster", new ForgeHexAmethystLootMod(new LootItemCondition[]{
LootTableIdCondition.builder(Blocks.AMETHYST_CLUSTER.getLootTable()).build()
}, HexLootHandler.DEFAULT_SHARD_MODIFICATION));
}
}

View file

@ -1,6 +1,7 @@
package at.petrak.hexcasting.forge.lib;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.forge.loot.ForgeHexAmethystLootMod;
import at.petrak.hexcasting.forge.loot.ForgeHexScrollLootMod;
import com.mojang.serialization.Codec;
import net.minecraftforge.common.loot.IGlobalLootModifier;
@ -14,4 +15,6 @@ public class ForgeHexLootMods {
public static final RegistryObject<Codec<ForgeHexScrollLootMod>> INJECT_SCROLLS = REGISTRY.register(
"inject_scrolls", ForgeHexScrollLootMod.CODEC);
public static final RegistryObject<Codec<ForgeHexAmethystLootMod>> AMETHYST = REGISTRY.register(
"amethyst_cluster", ForgeHexAmethystLootMod.CODEC);
}

View file

@ -0,0 +1,50 @@
package at.petrak.hexcasting.forge.loot;
import at.petrak.hexcasting.common.loot.AmethystReducerFunc;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.forge.lib.ForgeHexLootMods;
import com.google.common.base.Suppliers;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraftforge.common.loot.LootModifier;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public class ForgeHexAmethystLootMod extends LootModifier {
public static final Supplier<Codec<ForgeHexAmethystLootMod>> CODEC =
Suppliers.memoize(() -> RecordCodecBuilder.create(
inst -> codecStart(inst).and(
Codec.DOUBLE.fieldOf("shardDelta").forGetter(it -> it.shardDelta)
).apply(inst, ForgeHexAmethystLootMod::new)
));
public final double shardDelta;
public ForgeHexAmethystLootMod(LootItemCondition[] conditionsIn, double shardDelta) {
super(conditionsIn);
this.shardDelta = shardDelta;
}
@Override
protected @NotNull ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot,
LootContext context) {
var injectPool = context.getLootTable(HexLootHandler.TABLE_INJECT_AMETHYST_CLUSTER);
injectPool.getRandomItemsRaw(context, generatedLoot::add);
for (var stack : generatedLoot) {
AmethystReducerFunc.doStatic(stack, context, this.shardDelta);
}
return generatedLoot;
}
@Override
public Codec<ForgeHexAmethystLootMod> codec() {
return ForgeHexLootMods.AMETHYST.get();
}
}

View file

@ -1,6 +1,9 @@
package at.petrak.hexcasting.forge.loot;
import at.petrak.hexcasting.api.misc.ScrollQuantity;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.loot.AddPerWorldPatternToScrollFunc;
import at.petrak.hexcasting.common.loot.HexLootHandler;
import at.petrak.hexcasting.forge.lib.ForgeHexLootMods;
import com.google.common.base.Suppliers;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
@ -18,27 +21,31 @@ public class ForgeHexScrollLootMod extends LootModifier {
public static final Supplier<Codec<ForgeHexScrollLootMod>> CODEC =
Suppliers.memoize(() -> RecordCodecBuilder.create(
inst -> codecStart(inst).and(
Codec.INT.fieldOf("quantity").forGetter(it -> it.quantity.ordinal())
).apply(inst, (cond, quant) -> new ForgeHexScrollLootMod(cond, ScrollQuantity.values()[quant]))
Codec.INT.fieldOf("countRange").forGetter(it -> it.countRange)
).apply(inst, ForgeHexScrollLootMod::new)
));
public final ScrollQuantity quantity;
public final int countRange;
public ForgeHexScrollLootMod(LootItemCondition[] conditionsIn, ScrollQuantity quantity) {
public ForgeHexScrollLootMod(LootItemCondition[] conditionsIn, int countRange) {
super(conditionsIn);
this.quantity = quantity;
this.countRange = countRange;
}
@Override
protected @NotNull ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot,
LootContext context) {
var injectedTable = context.getLootTable(this.quantity.getPool());
injectedTable.getRandomItemsRaw(context, generatedLoot::add);
int count = HexLootHandler.getScrollCount(this.countRange, context.getRandom());
for (int i = 0; i < count; i++) {
var newStack = new ItemStack(HexItems.SCROLL_LARGE);
AddPerWorldPatternToScrollFunc.doStatic(newStack, context);
generatedLoot.add(newStack);
}
return generatedLoot;
}
@Override
public Codec<? extends IGlobalLootModifier> codec() {
return null;
return ForgeHexLootMods.INJECT_SCROLLS.get();
}
}