mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-28 11:29:17 +00:00
refactor crops
This commit is contained in:
@@ -62,4 +62,4 @@ categories:
|
||||
- default:flame_cane
|
||||
- default:gunpowder_block
|
||||
- default:solid_gunpowder_block
|
||||
- default:ender_pearl_crop_seed
|
||||
- default:ender_pearl_flower_seed
|
||||
@@ -4,7 +4,7 @@ i18n:
|
||||
item.fairy_flower: "Fairy Flower"
|
||||
item.reed: "Reed"
|
||||
item.flame_cane: "Flame Cane"
|
||||
item.ender_pearl_crop_seed: "Ender Pearl Flower Seeds"
|
||||
item.ender_pearl_flower_seed: "Ender Pearl Flower Seeds"
|
||||
item.bench: "Bench"
|
||||
item.table_lamp: "Table Lamp"
|
||||
item.wooden_chair: "Wooden Chair"
|
||||
@@ -44,7 +44,7 @@ i18n:
|
||||
item.fairy_flower: "仙灵花"
|
||||
item.reed: "芦苇"
|
||||
item.flame_cane: "烈焰甘蔗"
|
||||
item.ender_pearl_crop_seed: "末影珍珠花种子"
|
||||
item.ender_pearl_flower_seed: "末影珍珠花种子"
|
||||
item.bench: "长椅"
|
||||
item.table_lamp: "台灯"
|
||||
item.wooden_chair: "木椅"
|
||||
|
||||
@@ -35,18 +35,18 @@ items:
|
||||
behavior:
|
||||
type: block_item
|
||||
block: default:flame_cane
|
||||
default:ender_pearl_crop_seed:
|
||||
default:ender_pearl_flower_seed:
|
||||
material: paper
|
||||
custom-model-data: 4003
|
||||
data:
|
||||
item-name: "<!i><i18n:item.ender_pearl_crop_seed>"
|
||||
item-name: "<!i><i18n:item.ender_pearl_flower_seed>"
|
||||
model:
|
||||
template: default:model/simplified_generated
|
||||
arguments:
|
||||
path: "minecraft:block/custom/ender_pearl_crop_seed"
|
||||
path: "minecraft:block/custom/ender_pearl_flower_seed"
|
||||
behavior:
|
||||
type: block_item
|
||||
block: default:ender_pearl_crop
|
||||
block: default:ender_pearl_flower
|
||||
blocks:
|
||||
default:fairy_flower:
|
||||
settings:
|
||||
@@ -179,15 +179,15 @@ blocks:
|
||||
age=5:
|
||||
appearance: default
|
||||
id: 7
|
||||
default:ender_pearl_crop:
|
||||
default:ender_pearl_flower:
|
||||
settings:
|
||||
template:
|
||||
- default:hardness/none
|
||||
- default:sound/grass
|
||||
overrides:
|
||||
item: default:ender_pearl_crop_seed
|
||||
item: default:ender_pearl_flower_seed
|
||||
push-reaction: DESTROY
|
||||
map-color: 15
|
||||
map-color: 24
|
||||
is-randomly-ticking: true
|
||||
behavior:
|
||||
type: crop_block
|
||||
@@ -196,64 +196,47 @@ blocks:
|
||||
bottom-blocks:
|
||||
- minecraft:end_stone
|
||||
loot:
|
||||
pools:
|
||||
- rolls: 1
|
||||
entries:
|
||||
- type: item
|
||||
item: "default:ender_pearl_crop_seed"
|
||||
conditions:
|
||||
- type: survives_explosion
|
||||
- rolls:
|
||||
type: uniform
|
||||
min: "1"
|
||||
max: "5"
|
||||
entries:
|
||||
- type: item
|
||||
item: "minecraft:ender_pearl"
|
||||
conditions:
|
||||
- type: crop_ripe
|
||||
template: default:loot_table/seed_crop
|
||||
arguments:
|
||||
crop_item: minecraft:ender_pearl
|
||||
crop_seed: default:ender_pearl_flower_seed
|
||||
ripe_age: 4
|
||||
states:
|
||||
properties:
|
||||
age:
|
||||
type: int
|
||||
default: 0
|
||||
range: 0~5
|
||||
range: 0~3
|
||||
appearances:
|
||||
default:
|
||||
stage_0:
|
||||
state: "tripwire:0"
|
||||
models:
|
||||
- path: "minecraft:block/custom/ender_pearl_flower_stage_0"
|
||||
stage_1:
|
||||
state: "tripwire:1"
|
||||
models:
|
||||
- path: "minecraft:block/custom/ender_pearl_flower_stage_1"
|
||||
stage_2:
|
||||
state: "tripwire:2"
|
||||
models:
|
||||
- path: "minecraft:block/custom/ender_pearl_flower_stage_2"
|
||||
stage_3:
|
||||
state: "sugar_cane:3"
|
||||
models:
|
||||
- path: "minecraft:block/custom/ender_pearl_crop_stage1"
|
||||
generation:
|
||||
parent: "minecraft:block/custom/tinted_cross"
|
||||
textures:
|
||||
"cross": "minecraft:block/custom/ender_pearl_crop_stage1"
|
||||
ripe:
|
||||
state: "sugar_cane:4"
|
||||
models:
|
||||
- path: "minecraft:block/custom/ender_pearl_crop_stage2"
|
||||
generation:
|
||||
parent: "minecraft:block/custom/tinted_cross"
|
||||
textures:
|
||||
"cross": "minecraft:block/custom/ender_pearl_crop_stage2"
|
||||
- path: "minecraft:block/custom/ender_pearl_flower_stage_3"
|
||||
variants:
|
||||
age=0:
|
||||
appearance: default
|
||||
id: 8
|
||||
appearance: stage_0
|
||||
id: 0
|
||||
age=1:
|
||||
appearance: default
|
||||
id: 9
|
||||
appearance: stage_1
|
||||
id: 1
|
||||
age=2:
|
||||
appearance: default
|
||||
id: 10
|
||||
appearance: stage_2
|
||||
id: 2
|
||||
age=3:
|
||||
appearance: default
|
||||
id: 11
|
||||
age=4:
|
||||
appearance: default
|
||||
id: 12
|
||||
age=5:
|
||||
appearance: ripe
|
||||
id: 13
|
||||
appearance: stage_3
|
||||
id: 8
|
||||
recipes:
|
||||
default:paper_from_reed:
|
||||
type: shaped
|
||||
|
||||
@@ -953,7 +953,12 @@ templates#recipes:
|
||||
|
||||
# loot tables
|
||||
templates#loot_tables:
|
||||
|
||||
# drop one item
|
||||
|
||||
# template: default:loot_table/basic
|
||||
# arguments:
|
||||
# item: the item
|
||||
default:loot_table/basic:
|
||||
pools:
|
||||
- rolls: 1
|
||||
@@ -962,7 +967,12 @@ templates#loot_tables:
|
||||
entries:
|
||||
- type: item
|
||||
item: "{item}"
|
||||
|
||||
# drop with silk touch
|
||||
|
||||
# template: default:loot_table/silk_touch
|
||||
# arguments:
|
||||
# item: the item
|
||||
default:loot_table/silk_touch:
|
||||
pools:
|
||||
- rolls: 1
|
||||
@@ -972,7 +982,78 @@ templates#loot_tables:
|
||||
entries:
|
||||
- type: item
|
||||
item: "{item}"
|
||||
# drop ores
|
||||
|
||||
# crop drops
|
||||
|
||||
# template: default:loot_table/seed_crop
|
||||
# arguments:
|
||||
# crop_item: the ripe crop
|
||||
# crop_seed: the seed of the crop
|
||||
# ripe_age: the max age
|
||||
default:loot_table/seed_crop:
|
||||
pools:
|
||||
- rolls: 1
|
||||
entries:
|
||||
- type: alternatives
|
||||
children:
|
||||
- type: item
|
||||
item: "{crop_item}"
|
||||
conditions:
|
||||
- type: match_block_property
|
||||
properties:
|
||||
age: "{ripe_age}"
|
||||
- type: item
|
||||
item: "{crop_seed}"
|
||||
- rolls: 1
|
||||
conditions:
|
||||
- type: match_block_property
|
||||
properties:
|
||||
age: "{ripe_age}"
|
||||
entries:
|
||||
- type: item
|
||||
item: "{crop_seed}"
|
||||
functions:
|
||||
- type: apply_bonus
|
||||
enchantment: minecraft:fortune
|
||||
formula:
|
||||
type: binomial_with_bonus_count
|
||||
extra: 3
|
||||
probability: 0.5714286
|
||||
|
||||
# template: default:loot_table/crop
|
||||
# arguments:
|
||||
# crop_item: the ripe crop
|
||||
# ripe_age: the max age
|
||||
default:loot_table/crop:
|
||||
pools:
|
||||
- rolls: 1
|
||||
entries:
|
||||
- type: item
|
||||
item: "{crop_item}"
|
||||
- rolls: 1
|
||||
conditions:
|
||||
- type: match_block_property
|
||||
properties:
|
||||
age: "{ripe_age}"
|
||||
entries:
|
||||
- type: item
|
||||
item: "{crop_item}"
|
||||
functions:
|
||||
- type: apply_bonus
|
||||
enchantment: minecraft:fortune
|
||||
formula:
|
||||
type: binomial_with_bonus_count
|
||||
extra: 3
|
||||
probability: 0.5714286
|
||||
|
||||
# ore drops
|
||||
|
||||
# template: default:loot_table/ore
|
||||
# arguments:
|
||||
# ore_block: the ore block
|
||||
# ore_drop: the drops of the ore
|
||||
# min_exp: the min exp to drop
|
||||
# max_exp: the max exp to drop
|
||||
default:loot_table/ore:
|
||||
pools:
|
||||
- rolls: 1
|
||||
@@ -997,7 +1078,37 @@ templates#loot_tables:
|
||||
type: uniform
|
||||
min: "{min_exp}"
|
||||
max: "{max_exp}"
|
||||
# leaves
|
||||
|
||||
# template: default:loot_table/ore_no_exp
|
||||
# arguments:
|
||||
# ore_block: the ore block
|
||||
# ore_drop: the drops of the ore
|
||||
default:loot_table/ore_no_exp:
|
||||
pools:
|
||||
- rolls: 1
|
||||
entries:
|
||||
- type: alternatives
|
||||
children:
|
||||
- type: item
|
||||
item: "{ore_block}"
|
||||
conditions:
|
||||
- type: enchantment
|
||||
predicate: minecraft:silk_touch>=1
|
||||
- type: item
|
||||
item: "{ore_drop}"
|
||||
functions:
|
||||
- type: apply_bonus
|
||||
enchantment: minecraft:fortune
|
||||
formula:
|
||||
type: ore_drops
|
||||
- type: explosion_decay
|
||||
|
||||
# leaves drops
|
||||
|
||||
# template: default:loot_table/leaves
|
||||
# arguments:
|
||||
# leaves: the leaves block
|
||||
# sapling: the sapling item
|
||||
default:loot_table/leaves:
|
||||
pools:
|
||||
- rolls: 1
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"ambientocclusion": false,
|
||||
"textures": {
|
||||
"particle": "#cross"
|
||||
},
|
||||
"elements": [
|
||||
{ "from": [ 0.8, 0, 8 ],
|
||||
"to": [ 15.2, 16, 8 ],
|
||||
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": 45, "rescale": true },
|
||||
"shade": false,
|
||||
"faces": {
|
||||
"north": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" },
|
||||
"south": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" }
|
||||
}
|
||||
},
|
||||
{ "from": [ 8, 0, 0.8 ],
|
||||
"to": [ 8, 16, 15.2 ],
|
||||
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": 45, "rescale": true },
|
||||
"shade": false,
|
||||
"faces": {
|
||||
"west": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" },
|
||||
"east": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -182,11 +182,6 @@ public final class CraftEngineBlocks {
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withOptionalParameter(LootParameters.TOOL, serverPlayer.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
}
|
||||
if (state.behavior() instanceof CropBlockBehavior cropBlockBehavior) {
|
||||
if (cropBlockBehavior.isMaxAge(state)) {
|
||||
builder.withParameter(LootParameters.CROP_RIPE, true);
|
||||
}
|
||||
}
|
||||
for (Item<?> item : state.getDrops(builder, world)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
|
||||
@@ -139,11 +139,6 @@ public class BlockEventListener implements Listener {
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.PLAYER, serverPlayer);
|
||||
builder.withOptionalParameter(LootParameters.TOOL, itemInHand);
|
||||
if (state.behavior() instanceof CropBlockBehavior cropBlockBehavior) {
|
||||
if (cropBlockBehavior.isMaxAge(state)) {
|
||||
builder.withParameter(LootParameters.CROP_RIPE, true);
|
||||
}
|
||||
}
|
||||
for (Item<Object> item : state.getDrops(builder, world)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
@@ -302,11 +297,6 @@ public class BlockEventListener implements Listener {
|
||||
if (yield < 1f) {
|
||||
builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0f / yield);
|
||||
}
|
||||
if (state.behavior() instanceof CropBlockBehavior cropBlockBehavior) {
|
||||
if (cropBlockBehavior.isMaxAge(state)) {
|
||||
builder.withParameter(LootParameters.CROP_RIPE, true);
|
||||
}
|
||||
}
|
||||
for (Item<Object> item : state.getDrops(builder, world)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
|
||||
@@ -71,11 +71,6 @@ public class BushBlockBehavior extends AbstractBlockBehavior {
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
builder.withParameter(LootParameters.LOCATION, vec3d);
|
||||
builder.withParameter(LootParameters.WORLD, world);
|
||||
if (this instanceof CropBlockBehavior cropBlockBehavior) {
|
||||
if (cropBlockBehavior.isMaxAge(state)) {
|
||||
builder.withParameter(LootParameters.CROP_RIPE, true);
|
||||
}
|
||||
}
|
||||
for (Item<Object> item : previousState.getDrops(builder, world)) {
|
||||
world.dropItemNaturally(vec3d, item);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
@@ -37,6 +38,7 @@ public class CropBlockBehavior extends BushBlockBehavior {
|
||||
public final boolean isMaxAge(Object state) {
|
||||
return this.getAge(state) >= this.ageProperty.max;
|
||||
}
|
||||
|
||||
public final boolean isMaxAge(ImmutableBlockState state) {
|
||||
return this.getAge(state) >= this.ageProperty.max;
|
||||
}
|
||||
@@ -48,6 +50,7 @@ public class CropBlockBehavior extends BushBlockBehavior {
|
||||
public final int getAge(Object state) {
|
||||
return getCEBlockState(state).get(ageProperty);
|
||||
}
|
||||
|
||||
public final int getAge(ImmutableBlockState state) {
|
||||
return state.get(ageProperty);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
# Q: When do I need to configure this file?
|
||||
# A: When the number of real block IDs is insufficient, but there are still available appearances.
|
||||
|
||||
# By default, the plugin only registers an additional 112 oak leaf block states (for the default configuration needs [>=28 states]).
|
||||
minecraft:oak_leaves: 112
|
||||
|
||||
minecraft:oak_sapling: 1
|
||||
minecraft:birch_sapling: 1
|
||||
minecraft:spruce_sapling: 1
|
||||
@@ -24,5 +22,5 @@ minecraft:jungle_sapling: 1
|
||||
minecraft:dark_oak_sapling: 1
|
||||
minecraft:acacia_sapling: 1
|
||||
minecraft:cherry_sapling: 1
|
||||
|
||||
minecraft:anvil: 2
|
||||
minecraft:anvil: 2
|
||||
minecraft:sugarcane: 14
|
||||
@@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.loot.function.LootFunction;
|
||||
import net.momirealms.craftengine.core.loot.function.LootFunctions;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.loot.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -43,19 +44,19 @@ public class LootTable<T> {
|
||||
NumberProvider rolls = NumberProviders.fromObject(pool.getOrDefault("rolls", 1));
|
||||
NumberProvider bonus_rolls = NumberProviders.fromObject(pool.getOrDefault("bonus_rolls", 0));
|
||||
List<LootCondition> conditions = Optional.ofNullable(pool.get("conditions"))
|
||||
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
|
||||
.map(it -> LootConditions.fromMapList(MiscUtils.castToMapListOrThrow(it, () -> new RuntimeException("'conditions' should be a map list, current type: " + it.getClass().getSimpleName()))))
|
||||
.orElse(Lists.newArrayList());
|
||||
List<LootEntryContainer<T>> containers = Optional.ofNullable(pool.get("entries"))
|
||||
.map(it -> (List<LootEntryContainer<T>>) new ArrayList<LootEntryContainer<T>>(LootEntryContainers.fromMapList((List<Map<String, Object>>) it)))
|
||||
.map(it -> (List<LootEntryContainer<T>>) new ArrayList<LootEntryContainer<T>>(LootEntryContainers.fromMapList(MiscUtils.castToMapListOrThrow(it, () -> new RuntimeException("'entries' should be a map list, current type: " + it.getClass().getSimpleName())))))
|
||||
.orElse(Lists.newArrayList());
|
||||
List<LootFunction<T>> functions = Optional.ofNullable(pool.get("functions"))
|
||||
.map(it -> (List<LootFunction<T>>) new ArrayList<LootFunction<T>>(LootFunctions.fromMapList((List<Map<String, Object>>) it)))
|
||||
.map(it -> (List<LootFunction<T>>) new ArrayList<LootFunction<T>>(LootFunctions.fromMapList(MiscUtils.castToMapListOrThrow(it, () -> new RuntimeException("'functions' should be a map list, current type: " + it.getClass().getSimpleName())))))
|
||||
.orElse(Lists.newArrayList());
|
||||
lootPools.add(new LootPool<>(containers, conditions, functions, rolls, bonus_rolls));
|
||||
}
|
||||
return new LootTable<>(lootPools,
|
||||
Optional.ofNullable(map.get("functions"))
|
||||
.map(it -> (List<LootFunction<T>>) new ArrayList<LootFunction<T>>(LootFunctions.fromMapList((List<Map<String, Object>>) it)))
|
||||
.map(it -> (List<LootFunction<T>>) new ArrayList<LootFunction<T>>(LootFunctions.fromMapList(MiscUtils.castToMapListOrThrow(it, () -> new RuntimeException("'functions' should be a map list, current type: " + it.getClass().getSimpleName())))))
|
||||
.orElse(Lists.newArrayList())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CropRipeCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public static final CropRipeCondition INSTANCE = new CropRipeCondition();
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.CROP_RIPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
return lootContext.getOptionalParameter(LootParameters.CROP_RIPE).orElse(false);
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import java.util.function.Predicate;
|
||||
|
||||
public class LootConditions {
|
||||
public static final Key MATCH_ITEM = Key.from("craftengine:match_item");
|
||||
public static final Key MATCH_BLOCK_PROPERTY = Key.from("craftengine:match_block_property");
|
||||
public static final Key TABLE_BONUS = Key.from("craftengine:table_bonus");
|
||||
public static final Key SURVIVES_EXPLOSION = Key.from("craftengine:survives_explosion");
|
||||
public static final Key ANY_OF = Key.from("craftengine:any_of");
|
||||
@@ -21,10 +22,10 @@ public class LootConditions {
|
||||
public static final Key ENCHANTMENT = Key.from("craftengine:enchantment");
|
||||
public static final Key INVERTED = Key.from("craftengine:inverted");
|
||||
public static final Key FALLING_BLOCK = Key.from("craftengine:falling_block");
|
||||
public static final Key CROP_RIPE = Key.from("craftengine:crop_ripe");
|
||||
|
||||
static {
|
||||
register(MATCH_ITEM, MatchItemCondition.FACTORY);
|
||||
register(MATCH_BLOCK_PROPERTY, MatchBlockPropertyCondition.FACTORY);
|
||||
register(TABLE_BONUS, TableBonusCondition.FACTORY);
|
||||
register(SURVIVES_EXPLOSION, SurvivesExplosionCondition.FACTORY);
|
||||
register(ANY_OF, AnyOfCondition.FACTORY);
|
||||
@@ -32,7 +33,6 @@ public class LootConditions {
|
||||
register(ENCHANTMENT, EnchantmentCondition.FACTORY);
|
||||
register(INVERTED, InvertedCondition.FACTORY);
|
||||
register(FALLING_BLOCK, FallingCondition.FACTORY);
|
||||
register(CROP_RIPE, CropRipeCondition.FACTORY);
|
||||
}
|
||||
|
||||
public static void register(Key key, LootConditionFactory factory) {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.momirealms.craftengine.core.loot.condition;
|
||||
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.loot.LootContext;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.Pair;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MatchBlockPropertyCondition implements LootCondition {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final List<Pair<String, String>> properties;
|
||||
|
||||
public MatchBlockPropertyCondition(List<Pair<String, String>> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return LootConditions.MATCH_BLOCK_PROPERTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(LootContext lootContext) {
|
||||
return lootContext.getOptionalParameter(LootParameters.BLOCK_STATE).map(state -> {
|
||||
CustomBlock block = state.owner().value();
|
||||
for (Pair<String, String> property : this.properties) {
|
||||
Property<?> propertyIns = block.getProperty(property.left());
|
||||
if (propertyIns == null) {
|
||||
return false;
|
||||
}
|
||||
if (!state.get(propertyIns).toString().toLowerCase(Locale.ENGLISH).equals(property.right())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}).orElse(false);
|
||||
}
|
||||
|
||||
public static class Factory implements LootConditionFactory {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootCondition create(Map<String, Object> arguments) {
|
||||
Map<String, Object> properties = (Map<String, Object>) arguments.get("properties");
|
||||
if (properties == null) {
|
||||
throw new IllegalArgumentException("Missing 'properties' argument for 'match_block_property'");
|
||||
}
|
||||
List<Pair<String, String>> propertyList = new ArrayList<>();
|
||||
for (Map.Entry<String, Object> entry : properties.entrySet()) {
|
||||
propertyList.add(new Pair<>(entry.getKey(), entry.getValue().toString()));
|
||||
}
|
||||
return new MatchBlockPropertyCondition(propertyList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -78,9 +79,11 @@ public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<
|
||||
|
||||
public static class Formulas {
|
||||
public static final Key ORE_DROPS = Key.of("craftengine:ore_drops");
|
||||
public static final Key CROP_DROPS = Key.of("craftengine:binomial_with_bonus_count");
|
||||
|
||||
static {
|
||||
register(ORE_DROPS, OreDrops.FACTORY);
|
||||
register(CROP_DROPS, CropDrops.FACTORY);
|
||||
}
|
||||
|
||||
public static void register(Key key, FormulaFactory factory) {
|
||||
@@ -133,4 +136,40 @@ public class ApplyBonusCountFunction<T> extends AbstractLootConditionalFunction<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class CropDrops implements Formula {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final int extra;
|
||||
private final float probability;
|
||||
|
||||
public CropDrops(int extra, float probability) {
|
||||
this.extra = extra;
|
||||
this.probability = probability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int apply(int initialCount, int enchantmentLevel) {
|
||||
for (int i = 0; i < enchantmentLevel + this.extra; i++) {
|
||||
if (RandomUtils.generateRandomFloat(0,1) < this.probability) {
|
||||
initialCount++;
|
||||
}
|
||||
}
|
||||
return initialCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return Formulas.CROP_DROPS;
|
||||
}
|
||||
|
||||
public static class Factory implements FormulaFactory {
|
||||
|
||||
@Override
|
||||
public Formula create(Map<String, Object> arguments) {
|
||||
int extra = MiscUtils.getAsInt(arguments.getOrDefault("extra", 1));
|
||||
float probability = MiscUtils.getAsFloat(arguments.getOrDefault("probability", 0.5f));
|
||||
return new CropDrops(extra, probability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,5 +18,4 @@ public class LootParameters {
|
||||
public static final ContextKey<Player> PLAYER = new ContextKey<>(Key.of("craftengine:player"));
|
||||
public static final ContextKey<Item<?>> TOOL = new ContextKey<>(Key.of("craftengine:tool"));
|
||||
public static final ContextKey<ImmutableBlockState> BLOCK_STATE = new ContextKey<>(Key.of("craftengine:block_state"));
|
||||
public static final ContextKey<Boolean> CROP_RIPE = new ContextKey<>(Key.of("craftengine:crop_ripe"));
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.joml.Vector3f;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MiscUtils {
|
||||
|
||||
@@ -22,6 +23,15 @@ public class MiscUtils {
|
||||
throw new IllegalArgumentException("Expected Map, got: " + obj.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Map<String, Object>> castToMapListOrThrow(Object obj, Supplier<RuntimeException> exceptionSupplier) {
|
||||
if (obj instanceof List<?> list) {
|
||||
return (List<Map<String, Object>>) list;
|
||||
} else {
|
||||
throw exceptionSupplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Object> castToList(Object obj, boolean allowNull) {
|
||||
if (allowNull && obj == null) {
|
||||
|
||||
Reference in New Issue
Block a user