mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
@@ -135,7 +135,7 @@ repositories {
|
||||
```
|
||||
```kotlin
|
||||
dependencies {
|
||||
compileOnly("net.momirealms:craft-engine-core:0.0.29")
|
||||
compileOnly("net.momirealms:craft-engine-bukkit:0.0.29")
|
||||
compileOnly("net.momirealms:craft-engine-core:0.0.34")
|
||||
compileOnly("net.momirealms:craft-engine-bukkit:0.0.34")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow") version "9.0.0-beta6"
|
||||
id("com.gradleup.shadow") version "9.0.0-beta11"
|
||||
id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,9 @@ resource-pack:
|
||||
obfuscation:
|
||||
enable: false
|
||||
seed: 0 # 0 = random seed
|
||||
fake-directory: true
|
||||
escape-unicode: true
|
||||
fake-directory: false
|
||||
escape-unicode: false
|
||||
break-json: false
|
||||
resource-location:
|
||||
enable: true
|
||||
random-namespace:
|
||||
@@ -183,12 +184,14 @@ gui:
|
||||
title: "<white><shift:-11><image:internal:cooking_recipe><shift:-136><image:internal:smelting>"
|
||||
smoking:
|
||||
title: "<white><shift:-11><image:internal:cooking_recipe><shift:-136><image:internal:smoking>"
|
||||
campfire:
|
||||
campfire-cooking:
|
||||
title: "<white><shift:-11><image:internal:cooking_recipe><shift:-136><image:internal:campfire>"
|
||||
crafting:
|
||||
title: "<white><shift:-11><image:internal:crafting_recipe>"
|
||||
stonecutting:
|
||||
title: "<white><shift:-11><image:internal:stonecutting_recipe>"
|
||||
smithing-transform:
|
||||
title: "<white><shift:-11><image:internal:smithing_transform_recipe>"
|
||||
|
||||
performance:
|
||||
# Maximum chain update depth when fixing client visuals
|
||||
|
||||
@@ -329,4 +329,70 @@ recipes#11:
|
||||
B: "minecraft:stick"
|
||||
result:
|
||||
id: default:topaz_pickaxe
|
||||
count: 1
|
||||
default:topaz_helmet:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "AAA"
|
||||
- "A A"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_helmet
|
||||
count: 1
|
||||
default:topaz_chestplate:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "A A"
|
||||
- "AAA"
|
||||
- "AAA"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_chestplate
|
||||
count: 1
|
||||
default:topaz_leggings:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "AAA"
|
||||
- "A A"
|
||||
- "A A"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_leggings
|
||||
count: 1
|
||||
default:topaz_boots:
|
||||
type: shaped
|
||||
pattern:
|
||||
- "A A"
|
||||
- "A A"
|
||||
ingredients:
|
||||
A: "default:topaz"
|
||||
result:
|
||||
id: default:topaz_boots
|
||||
count: 1
|
||||
default:topaz_bow:
|
||||
type: smithing_transform
|
||||
base: minecraft:bow
|
||||
addition: default:topaz
|
||||
template-type: default:topaz
|
||||
result:
|
||||
id: default:topaz_bow
|
||||
count: 1
|
||||
default:topaz_crossbow:
|
||||
type: smithing_transform
|
||||
base: minecraft:crossbow
|
||||
addition: default:topaz
|
||||
template-type: default:topaz
|
||||
result:
|
||||
id: default:topaz_crossbow
|
||||
count: 1
|
||||
default:topaz_rod:
|
||||
type: smithing_transform
|
||||
base: minecraft:fishing_rod
|
||||
addition: default:topaz
|
||||
template-type: default:topaz
|
||||
result:
|
||||
id: default:topaz_rod
|
||||
count: 1
|
||||
@@ -314,12 +314,12 @@ recipes:
|
||||
default:palm_planks:
|
||||
template: default:recipe/planks
|
||||
arguments:
|
||||
tree_type: palm
|
||||
wood_type: palm
|
||||
default:palm_wood:
|
||||
template: default:recipe/log_2_wood
|
||||
arguments:
|
||||
tree_type: palm
|
||||
wood_type: palm
|
||||
default:stripped_palm_wood:
|
||||
template: default:recipe/log_2_wood
|
||||
arguments:
|
||||
tree_type: stripped_palm
|
||||
wood_type: stripped_palm
|
||||
@@ -33,9 +33,31 @@ templates#models#block:
|
||||
textures:
|
||||
"end": "{end_texture}"
|
||||
"side": "{side_texture}"
|
||||
# template: default:model/cube
|
||||
# arguments:
|
||||
# model: model_path
|
||||
# particle_texture: particle_texture_path
|
||||
# down_texture: down_texture_path
|
||||
# up_texture: up_texture_path
|
||||
# north_texture: north_texture_path
|
||||
# east_texture: east_texture_path
|
||||
# south_texture: south_texture_path
|
||||
# west_texture: west_texture_path
|
||||
default:model/cube:
|
||||
path: "{model}"
|
||||
generation:
|
||||
parent: "minecraft:block/cube_column"
|
||||
textures:
|
||||
"particle": "minecraft:block/custom/block_particle"
|
||||
"down": "minecraft:block/custom/block_down"
|
||||
"up": "minecraft:block/custom/block_up"
|
||||
"north": "minecraft:block/custom/block_north"
|
||||
"east": "minecraft:block/custom/block_east"
|
||||
"south": "minecraft:block/custom/block_south"
|
||||
"west": "minecraft:block/custom/block_west"
|
||||
|
||||
# 2D items
|
||||
templates#models#generated:
|
||||
templates#models#2d:
|
||||
# template: default:model/generated
|
||||
# arguments:
|
||||
# model: model_path
|
||||
@@ -92,6 +114,22 @@ templates#models#generated:
|
||||
textures:
|
||||
"layer0": "{path}"
|
||||
|
||||
# shield
|
||||
templates#models#shield:
|
||||
# template: default:model/shield_3d
|
||||
# arguments:
|
||||
# model: shield_model_path
|
||||
# block_model: shield_block_model_path
|
||||
default:model/shield_3d:
|
||||
type: "minecraft:condition"
|
||||
property: "minecraft:using_item"
|
||||
on-false:
|
||||
type: minecraft:model
|
||||
path: "{model}"
|
||||
on-true:
|
||||
type: minecraft:model
|
||||
path: "{block_model}"
|
||||
|
||||
# fishing rods
|
||||
templates#models#fishing_rod:
|
||||
# template: default:model/fishing_rod_3d
|
||||
@@ -258,14 +296,14 @@ templates#models#crossbow:
|
||||
- when: arrow
|
||||
model:
|
||||
type: minecraft:model
|
||||
path: "{arrow_path}"
|
||||
path: "{arrow_model}"
|
||||
- when: rocket
|
||||
model:
|
||||
type: minecraft:model
|
||||
path: "{firework_model}"
|
||||
fallback:
|
||||
type: minecraft:model
|
||||
path: "{path}"
|
||||
path: "{model}"
|
||||
on-true:
|
||||
type: "minecraft:range_dispatch"
|
||||
property: "minecraft:crossbow/pull"
|
||||
@@ -305,7 +343,7 @@ templates#models#crossbow:
|
||||
- when: arrow
|
||||
model:
|
||||
type: minecraft:model
|
||||
path: "{arrow_path}"
|
||||
path: "{arrow_model}"
|
||||
generation:
|
||||
parent: "minecraft:item/crossbow_arrow"
|
||||
textures:
|
||||
@@ -320,7 +358,7 @@ templates#models#crossbow:
|
||||
"layer0": "{firework_texture}"
|
||||
fallback:
|
||||
type: minecraft:model
|
||||
path: "{path}"
|
||||
path: "{model}"
|
||||
generation:
|
||||
parent: "minecraft:item/crossbow"
|
||||
textures:
|
||||
@@ -339,7 +377,7 @@ templates#models#crossbow:
|
||||
threshold: 0.58
|
||||
- model:
|
||||
type: minecraft:model
|
||||
path: "{pulling_2_path}"
|
||||
path: "{pulling_2_model}"
|
||||
generation:
|
||||
parent: "minecraft:item/crossbow_pulling_2"
|
||||
textures:
|
||||
@@ -862,9 +900,9 @@ templates#recipes:
|
||||
category: building
|
||||
group: planks
|
||||
ingredients:
|
||||
A: "#default:{tree_type}_logs"
|
||||
A: "#default:{wood_type}_logs"
|
||||
result:
|
||||
id: "default:{tree_type}_planks"
|
||||
id: "default:{wood_type}_planks"
|
||||
count: 4
|
||||
default:recipe/log_2_wood:
|
||||
type: shaped
|
||||
@@ -874,9 +912,9 @@ templates#recipes:
|
||||
- "AA"
|
||||
- "AA"
|
||||
ingredients:
|
||||
A: "default:{tree_type}_log"
|
||||
A: "default:{wood_type}_log"
|
||||
result:
|
||||
id: "default:{tree_type}_wood"
|
||||
id: "default:{wood_type}_wood"
|
||||
count: 3
|
||||
default:recipe/smelting_ore:
|
||||
type: smelting
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "item/custom/bench"
|
||||
"0": "item/custom/bench",
|
||||
"particle": "item/custom/bench"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"texture_size": [32, 32],
|
||||
"textures": {
|
||||
"0": "item/custom/table_lamp"
|
||||
"0": "item/custom/table_lamp",
|
||||
"particle": "item/custom/table_lamp"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"texture_size": [32, 32],
|
||||
"textures": {
|
||||
"0": "item/custom/wooden_chair"
|
||||
"0": "item/custom/wooden_chair",
|
||||
"particle": "item/custom/wooden_chair"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
|
||||
@@ -53,12 +53,18 @@ images:
|
||||
font: minecraft:internal
|
||||
file: minecraft:font/gui/custom/stonecutting_recipe.png
|
||||
char: '\ub008'
|
||||
internal:smithing_transform_recipe:
|
||||
height: 142
|
||||
ascent: 20
|
||||
font: minecraft:internal
|
||||
file: minecraft:font/gui/custom/smithing_transform_recipe.png
|
||||
char: '\ub009'
|
||||
internal:no_recipe:
|
||||
height: 140
|
||||
ascent: 18
|
||||
font: minecraft:internal
|
||||
file: minecraft:font/gui/custom/no_recipe.png
|
||||
char: '\ub009'
|
||||
char: '\ub00a'
|
||||
|
||||
templates:
|
||||
internal:icon/2d:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow") version "9.0.0-beta6"
|
||||
id("com.gradleup.shadow") version "9.0.0-beta11"
|
||||
id("maven-publish")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("io.github.goooler.shadow") version "8.1.8"
|
||||
id("com.gradleup.shadow") version "9.0.0-beta11"
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
||||
@@ -343,9 +343,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
return;
|
||||
}
|
||||
Vector3f seatPos = MiscUtils.getVector3f(vector3f);
|
||||
if (!furniture.releaseSeat(seatPos)) {
|
||||
plugin.logger().warn("Failed to release seat " + seatPos + " for player " + player.getName());
|
||||
}
|
||||
furniture.releaseSeat(seatPos);
|
||||
}
|
||||
|
||||
protected boolean isSeatCarrierType(Entity entity) {
|
||||
|
||||
@@ -4,6 +4,8 @@ import com.saicone.rtag.RtagItem;
|
||||
import net.momirealms.craftengine.core.item.ItemWrapper;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class RTagItemWrapper implements ItemWrapper<ItemStack> {
|
||||
private final RtagItem rtagItem;
|
||||
@@ -110,4 +112,9 @@ public class RTagItemWrapper implements ItemWrapper<ItemStack> {
|
||||
public ItemWrapper<ItemStack> copyWithCount(int count) {
|
||||
return new RTagItemWrapper(new RtagItem(this.rtagItem.loadCopy()), count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getData() {
|
||||
return this.rtagItem.get();
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
if (!InteractUtils.isInteractable(BlockStateUtils.getBlockOwnerIdFromState(state.vanillaBlockState().handle()),
|
||||
bukkitPlayer, BlockStateUtils.fromBlockData(state.vanillaBlockState().handle()),
|
||||
context.getHitResult(), item
|
||||
)) {
|
||||
) || player.isSecondaryUseActive()) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
// shrink item amount
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package net.momirealms.craftengine.bukkit.item.factory;
|
||||
|
||||
import com.saicone.rtag.RtagItem;
|
||||
import com.saicone.rtag.data.ComponentType;
|
||||
import com.saicone.rtag.item.ItemObject;
|
||||
import net.momirealms.craftengine.bukkit.item.RTagItemWrapper;
|
||||
import net.momirealms.craftengine.bukkit.util.EnchantmentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.item.ComponentKeys;
|
||||
import net.momirealms.craftengine.core.item.Enchantment;
|
||||
import net.momirealms.craftengine.core.item.ItemWrapper;
|
||||
@@ -287,4 +291,18 @@ public class ComponentItemFactory extends BukkitItemFactory {
|
||||
if (!item.hasComponent(ComponentKeys.REPAIR_COST)) return Optional.empty();
|
||||
return Optional.ofNullable((Integer) ComponentType.encodeJava(ComponentKeys.REPAIR_COST, item.getComponent(ComponentKeys.REPAIR_COST)).orElse(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemWrapper<ItemStack> merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
Object itemStack1 = item1.getLiteralObject();
|
||||
Object itemStack2 = item2.getLiteralObject();
|
||||
try {
|
||||
Object itemStack3 = Reflections.method$ItemStack$transmuteCopy.invoke(itemStack1, Reflections.method$ItemStack$getItem.invoke(itemStack2), 1);
|
||||
Reflections.method$ItemStack$applyComponents.invoke(itemStack3, Reflections.method$ItemStack$getComponentsPatch.invoke(itemStack2));
|
||||
return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack3)), item2.count());
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to merge item", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package net.momirealms.craftengine.bukkit.item.factory;
|
||||
|
||||
import com.saicone.rtag.RtagItem;
|
||||
import com.saicone.rtag.item.ItemObject;
|
||||
import com.saicone.rtag.tag.TagBase;
|
||||
import com.saicone.rtag.tag.TagCompound;
|
||||
import com.saicone.rtag.tag.TagList;
|
||||
import net.momirealms.craftengine.bukkit.item.RTagItemWrapper;
|
||||
import net.momirealms.craftengine.core.item.Enchantment;
|
||||
import net.momirealms.craftengine.core.item.ItemWrapper;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
@@ -123,18 +126,11 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
|
||||
@Override
|
||||
protected Optional<Integer> maxDamage(ItemWrapper<ItemStack> item) {
|
||||
// if (!item.hasTag("CustomFishing", "max_dur")) return Optional.empty();
|
||||
// return Optional.of(item.get("CustomFishing", "max_dur"));
|
||||
return Optional.of((int) item.getItem().getType().getMaxDurability());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void maxDamage(ItemWrapper<ItemStack> item, Integer damage) {
|
||||
// if (damage == null) {
|
||||
// item.remove("CustomFishing", "max_dur");
|
||||
// } else {
|
||||
// item.set(damage, "CustomFishing", "max_dur");
|
||||
// }
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@@ -217,6 +213,7 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
|
||||
@Override
|
||||
protected void maxStackSize(ItemWrapper<ItemStack> item, Integer maxStackSize) {
|
||||
throw new UnsupportedOperationException("This feature is only available on 1.20.5+");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -229,4 +226,13 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
if (!item.hasTag("RepairCost")) return Optional.empty();
|
||||
return Optional.of(item.get("RepairCost"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemWrapper<ItemStack> merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
Object itemStack = ItemObject.copy(item2.getLiteralObject());
|
||||
ItemObject.setCustomDataTag(itemStack, TagCompound.clone(ItemObject.getCustomDataTag(item1.getLiteralObject())));
|
||||
// one more step than vanilla
|
||||
TagCompound.merge(ItemObject.getCustomDataTag(itemStack), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
|
||||
return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count());
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,22 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
private static BukkitRecipeManager instance;
|
||||
|
||||
static {
|
||||
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SMITHING_TRANSFORM, (key, recipe) -> {
|
||||
CustomSmithingTransformRecipe<ItemStack> ceRecipe = (CustomSmithingTransformRecipe<ItemStack>) recipe;
|
||||
ceRecipe.addition();
|
||||
// bukkit api doesn't allow empty material choices, that's why we do this
|
||||
try {
|
||||
Object smithingRecipe = createMinecraftSmithingTransformRecipe(ceRecipe);
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
smithingRecipe = Reflections.constructor$RecipeHolder.newInstance(Reflections.method$CraftRecipe$toMinecraft.invoke(null, key), smithingRecipe);
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
smithingRecipe = Reflections.constructor$RecipeHolder.newInstance(Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, key.namespace(), key.value()), smithingRecipe);
|
||||
}
|
||||
Reflections.method$RecipeManager$addRecipe.invoke(minecraftRecipeManager(), smithingRecipe);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to convert transform recipe", e);
|
||||
}
|
||||
});
|
||||
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SHAPED, (key, recipe) -> {
|
||||
CustomShapedRecipe<ItemStack> ceRecipe = (CustomShapedRecipe<ItemStack>) recipe;
|
||||
ShapedRecipe shapedRecipe = new ShapedRecipe(key, ceRecipe.result(ItemBuildContext.EMPTY));
|
||||
@@ -65,7 +81,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
}
|
||||
shapedRecipe.shape(ceRecipe.pattern().pattern());
|
||||
for (Map.Entry<Character, Ingredient<ItemStack>> entry : ceRecipe.pattern().ingredients().entrySet()) {
|
||||
shapedRecipe.setIngredient(entry.getKey(), new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(entry.getValue())));
|
||||
shapedRecipe.setIngredient(entry.getKey(), ingredientToBukkitRecipeChoice(entry.getValue()));
|
||||
}
|
||||
try {
|
||||
Object craftRecipe = Reflections.method$CraftShapedRecipe$fromBukkitRecipe.invoke(null, shapedRecipe);
|
||||
@@ -85,7 +101,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
shapelessRecipe.setCategory(CraftingBookCategory.valueOf(Objects.requireNonNull(ceRecipe.category()).name()));
|
||||
}
|
||||
for (Ingredient<ItemStack> ingredient : ceRecipe.ingredientsInUse()) {
|
||||
shapelessRecipe.addIngredient(new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ingredient)));
|
||||
shapelessRecipe.addIngredient(ingredientToBukkitRecipeChoice(ingredient));
|
||||
}
|
||||
try {
|
||||
Object craftRecipe = Reflections.method$CraftShapelessRecipe$fromBukkitRecipe.invoke(null, shapelessRecipe);
|
||||
@@ -99,7 +115,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
CustomSmeltingRecipe<ItemStack> ceRecipe = (CustomSmeltingRecipe<ItemStack>) recipe;
|
||||
FurnaceRecipe furnaceRecipe = new FurnaceRecipe(
|
||||
key, ceRecipe.result(ItemBuildContext.EMPTY),
|
||||
new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())),
|
||||
ingredientToBukkitRecipeChoice(ceRecipe.ingredient()),
|
||||
ceRecipe.experience(), ceRecipe.cookingTime()
|
||||
);
|
||||
if (ceRecipe.group() != null) {
|
||||
@@ -120,7 +136,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
CustomSmokingRecipe<ItemStack> ceRecipe = (CustomSmokingRecipe<ItemStack>) recipe;
|
||||
SmokingRecipe smokingRecipe = new SmokingRecipe(
|
||||
key, ceRecipe.result(ItemBuildContext.EMPTY),
|
||||
new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())),
|
||||
ingredientToBukkitRecipeChoice(ceRecipe.ingredient()),
|
||||
ceRecipe.experience(), ceRecipe.cookingTime()
|
||||
);
|
||||
if (ceRecipe.group() != null) {
|
||||
@@ -141,7 +157,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
CustomBlastingRecipe<ItemStack> ceRecipe = (CustomBlastingRecipe<ItemStack>) recipe;
|
||||
BlastingRecipe blastingRecipe = new BlastingRecipe(
|
||||
key, ceRecipe.result(ItemBuildContext.EMPTY),
|
||||
new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())),
|
||||
ingredientToBukkitRecipeChoice(ceRecipe.ingredient()),
|
||||
ceRecipe.experience(), ceRecipe.cookingTime()
|
||||
);
|
||||
if (ceRecipe.group() != null) {
|
||||
@@ -162,7 +178,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) recipe;
|
||||
CampfireRecipe campfireRecipe = new CampfireRecipe(
|
||||
key, ceRecipe.result(ItemBuildContext.EMPTY),
|
||||
new RecipeChoice.MaterialChoice(ingredientToBukkitMaterials(ceRecipe.ingredient())),
|
||||
ingredientToBukkitRecipeChoice(ceRecipe.ingredient()),
|
||||
ceRecipe.experience(), ceRecipe.cookingTime()
|
||||
);
|
||||
if (ceRecipe.group() != null) {
|
||||
@@ -179,7 +195,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
CraftEngine.instance().logger().warn("Failed to convert campfire recipe", e);
|
||||
}
|
||||
});
|
||||
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONE_CUTTING, (key, recipe) -> {
|
||||
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONECUTTING, (key, recipe) -> {
|
||||
CustomStoneCuttingRecipe<ItemStack> ceRecipe = (CustomStoneCuttingRecipe<ItemStack>) recipe;
|
||||
List<ItemStack> itemStacks = new ArrayList<>();
|
||||
for (Holder<Key> item : ceRecipe.ingredient().items()) {
|
||||
@@ -366,9 +382,13 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
this.byType.computeIfAbsent(recipe.type(), k -> new ArrayList<>()).add(recipe);
|
||||
this.byId.put(id, recipe);
|
||||
this.byResult.computeIfAbsent(recipe.result().item().id(), k -> new ArrayList<>()).add(recipe);
|
||||
HashSet<Key> usedKeys = new HashSet<>();
|
||||
for (Ingredient<ItemStack> ingredient : recipe.ingredientsInUse()) {
|
||||
for (Holder<Key> holder : ingredient.items()) {
|
||||
this.byIngredient.computeIfAbsent(holder.value(), k -> new ArrayList<>()).add(recipe);
|
||||
Key key = holder.value();
|
||||
if (usedKeys.add(key)) {
|
||||
this.byIngredient.computeIfAbsent(key, k -> new ArrayList<>()).add(recipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -492,6 +512,10 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
VanillaStoneCuttingRecipe recipe = this.recipeReader.readStoneCutting(jsonObject);
|
||||
handleDataPackStoneCuttingRecipe(id, recipe);
|
||||
}
|
||||
case "minecraft:smithing_transform" -> {
|
||||
VanillaSmithingTransformRecipe recipe = this.recipeReader.readSmithingTransform(jsonObject);
|
||||
handleDataPackSmithingTransform(id, recipe, (injectLogics::add));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -517,6 +541,29 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
return future;
|
||||
}
|
||||
|
||||
private boolean readVanillaIngredients(boolean hasCustomItemInTag, List<String> ingredients, Consumer<Material> materialConsumer, Consumer<Holder<Key>> holderConsumer) {
|
||||
for (String item : ingredients) {
|
||||
if (item.charAt(0) == '#') {
|
||||
Key tag = Key.from(item.substring(1));
|
||||
for (Material material : tagToMaterials(tag)) {
|
||||
materialConsumer.accept(material);
|
||||
}
|
||||
if (!hasCustomItemInTag) {
|
||||
if (!plugin.itemManager().tagToCustomItems(tag).isEmpty()) {
|
||||
hasCustomItemInTag = true;
|
||||
}
|
||||
}
|
||||
for (Holder<Key> holder : plugin.itemManager().tagToItems(tag)) {
|
||||
holderConsumer.accept(holder);
|
||||
}
|
||||
} else {
|
||||
materialConsumer.accept(MaterialUtils.getMaterial(item));
|
||||
holderConsumer.accept(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow());
|
||||
}
|
||||
}
|
||||
return hasCustomItemInTag;
|
||||
}
|
||||
|
||||
private void handleDataPackShapelessRecipe(Key id, VanillaShapelessRecipe recipe, Consumer<Runnable> callback) {
|
||||
NamespacedKey key = new NamespacedKey(id.namespace(), id.value());
|
||||
ItemStack result = createResultStack(recipe.result());
|
||||
@@ -666,22 +713,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
Set<Material> materials = new HashSet<>();
|
||||
Set<Holder<Key>> holders = new HashSet<>();
|
||||
|
||||
boolean hasCustomItemInTag = false;
|
||||
for (String item : recipe.ingredient()) {
|
||||
if (item.charAt(0) == '#') {
|
||||
Key tag = Key.from(item.substring(1));
|
||||
materials.addAll(tagToMaterials(tag));
|
||||
if (!hasCustomItemInTag) {
|
||||
if (!plugin.itemManager().tagToCustomItems(tag).isEmpty()) {
|
||||
hasCustomItemInTag = true;
|
||||
}
|
||||
}
|
||||
holders.addAll(plugin.itemManager().tagToItems(tag));
|
||||
} else {
|
||||
materials.add(MaterialUtils.getMaterial(item));
|
||||
holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.from(item)).orElseThrow());
|
||||
}
|
||||
}
|
||||
boolean hasCustomItemInTag = readVanillaIngredients(false, recipe.ingredient(), materials::add, holders::add);
|
||||
org.bukkit.inventory.CookingRecipe<?> cookingRecipe = constructor1.apply(key, result, new RecipeChoice.MaterialChoice(new ArrayList<>(materials)), recipe.experience(), recipe.cookingTime());
|
||||
if (recipe.group() != null) {
|
||||
cookingRecipe.setGroup(recipe.group());
|
||||
@@ -714,6 +746,53 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
this.addInternalRecipe(id, ceRecipe);
|
||||
}
|
||||
|
||||
private void handleDataPackSmithingTransform(Key id, VanillaSmithingTransformRecipe recipe, Consumer<Runnable> callback) {
|
||||
NamespacedKey key = new NamespacedKey(id.namespace(), id.value());
|
||||
ItemStack result = createResultStack(recipe.result());
|
||||
boolean hasCustomItemInTag;
|
||||
|
||||
Set<Material> additionMaterials = new HashSet<>();
|
||||
Set<Holder<Key>> additionHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(false, recipe.addition(), additionMaterials::add, additionHolders::add);
|
||||
|
||||
Set<Material> templateMaterials = new HashSet<>();
|
||||
Set<Holder<Key>> templateHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.template(), templateMaterials::add, templateHolders::add);
|
||||
|
||||
Set<Material> baseMaterials = new HashSet<>();
|
||||
Set<Holder<Key>> baseHolders = new HashSet<>();
|
||||
hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.base(), baseMaterials::add, baseHolders::add);
|
||||
|
||||
CustomSmithingTransformRecipe<ItemStack> ceRecipe = new CustomSmithingTransformRecipe<>(
|
||||
id,
|
||||
baseHolders.isEmpty() ? null : Ingredient.of(baseHolders),
|
||||
templateHolders.isEmpty() ? null : Ingredient.of(templateHolders),
|
||||
additionHolders.isEmpty() ? null : Ingredient.of(additionHolders),
|
||||
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()),
|
||||
true,
|
||||
List.of()
|
||||
);
|
||||
|
||||
SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe(key, result,
|
||||
new RecipeChoice.MaterialChoice(new ArrayList<>(templateMaterials)),
|
||||
new RecipeChoice.MaterialChoice(new ArrayList<>(baseMaterials)),
|
||||
new RecipeChoice.MaterialChoice(new ArrayList<>(additionMaterials))
|
||||
);
|
||||
|
||||
if (hasCustomItemInTag) {
|
||||
callback.accept(() -> {
|
||||
try {
|
||||
unregisterRecipe(key);
|
||||
Reflections.method$CraftRecipe$addToCraftingManager.invoke(Reflections.method$CraftSmithingTransformRecipe$fromBukkitRecipe.invoke(null, transformRecipe));
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to convert transform recipe", e);
|
||||
}
|
||||
});
|
||||
this.injectedDataPackRecipes.add(key);
|
||||
}
|
||||
this.addInternalRecipe(id, ceRecipe);
|
||||
}
|
||||
|
||||
private List<Material> tagToMaterials(Key tag) {
|
||||
Set<Material> materials = new HashSet<>();
|
||||
List<Holder<Key>> holders = this.plugin.itemManager().tagToVanillaItems(tag);
|
||||
@@ -763,12 +842,12 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
return Key.of(prefix, fileName);
|
||||
}
|
||||
|
||||
private static List<Material> ingredientToBukkitMaterials(Ingredient<ItemStack> ingredient) {
|
||||
private static RecipeChoice ingredientToBukkitRecipeChoice(Ingredient<ItemStack> ingredient) {
|
||||
Set<Material> materials = new HashSet<>();
|
||||
for (Holder<Key> holder : ingredient.items()) {
|
||||
materials.add(getMaterialById(holder.value()));
|
||||
}
|
||||
return new ArrayList<>(materials);
|
||||
return new RecipeChoice.MaterialChoice(new ArrayList<>(materials));
|
||||
}
|
||||
|
||||
private static Material getMaterialById(Key key) {
|
||||
@@ -888,6 +967,53 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
}
|
||||
}
|
||||
|
||||
// 1.20-1.21.2
|
||||
private static Object toMinecraftIngredient(Ingredient<ItemStack> ingredient) throws ReflectiveOperationException {
|
||||
if (ingredient == null) {
|
||||
return Reflections.method$CraftRecipe$toIngredient.invoke(null, null, true);
|
||||
} else {
|
||||
RecipeChoice choice = ingredientToBukkitRecipeChoice(ingredient);
|
||||
return Reflections.method$CraftRecipe$toIngredient.invoke(null, choice, true);
|
||||
}
|
||||
}
|
||||
|
||||
// 1.21.2+
|
||||
private static Optional<Object> toOptionalMinecraftIngredient(Ingredient<ItemStack> ingredient) throws ReflectiveOperationException {
|
||||
if (ingredient == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
RecipeChoice choice = ingredientToBukkitRecipeChoice(ingredient);
|
||||
Object mcIngredient = Reflections.method$CraftRecipe$toIngredient.invoke(null, choice, true);
|
||||
return Optional.of(mcIngredient);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object createMinecraftSmithingTransformRecipe(CustomSmithingTransformRecipe<ItemStack> ceRecipe) throws ReflectiveOperationException {
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
return Reflections.constructor$SmithingTransformRecipe.newInstance(
|
||||
toOptionalMinecraftIngredient(ceRecipe.template()),
|
||||
toOptionalMinecraftIngredient(ceRecipe.base()),
|
||||
toOptionalMinecraftIngredient(ceRecipe.addition()),
|
||||
Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY))
|
||||
);
|
||||
} else if (VersionHelper.isVersionNewerThan1_20_2()) {
|
||||
return Reflections.constructor$SmithingTransformRecipe.newInstance(
|
||||
toMinecraftIngredient(ceRecipe.template()),
|
||||
toMinecraftIngredient(ceRecipe.base()),
|
||||
toMinecraftIngredient(ceRecipe.addition()),
|
||||
Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY))
|
||||
);
|
||||
} else {
|
||||
return Reflections.constructor$SmithingTransformRecipe.newInstance(
|
||||
Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, ceRecipe.id().namespace(), ceRecipe.id().value()),
|
||||
toMinecraftIngredient(ceRecipe.template()),
|
||||
toMinecraftIngredient(ceRecipe.base()),
|
||||
toMinecraftIngredient(ceRecipe.addition()),
|
||||
Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getRecipeHolderByRecipe(Recipe<ItemStack> recipe) {
|
||||
return recipeToMcRecipeHolder.get(recipe);
|
||||
}
|
||||
|
||||
@@ -11,12 +11,11 @@ import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.item.*;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomCampfireRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.item.recipe.*;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
@@ -38,6 +37,7 @@ import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.*;
|
||||
import org.bukkit.inventory.view.AnvilView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -832,4 +832,71 @@ public class RecipeEventListener implements Listener {
|
||||
plugin.logger().warn("Failed to correct used recipe", e);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onSmithingTransform(PrepareSmithingEvent event) {
|
||||
if (!ConfigManager.enableRecipeSystem()) return;
|
||||
SmithingInventory inventory = event.getInventory();
|
||||
if (!(inventory.getRecipe() instanceof SmithingTransformRecipe recipe)) return;
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack base = inventory.getInputEquipment();
|
||||
ItemStack template = inventory.getInputTemplate();
|
||||
ItemStack addition = inventory.getInputMineral();
|
||||
|
||||
SmithingInput<ItemStack> input = new SmithingInput<>(
|
||||
getOptimizedIDItem(base),
|
||||
getOptimizedIDItem(template),
|
||||
getOptimizedIDItem(addition)
|
||||
);
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SMITHING_TRANSFORM, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player;
|
||||
try {
|
||||
player = (Player) Reflections.method$InventoryView$getPlayer.invoke(event.getView());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to get inventory viewer", e);
|
||||
return;
|
||||
}
|
||||
|
||||
CustomSmithingTransformRecipe<ItemStack> transformRecipe = (CustomSmithingTransformRecipe<ItemStack>) ceRecipe;
|
||||
ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base));
|
||||
event.setResult(processed);
|
||||
correctSmithingRecipeUsed(inventory, ceRecipe);
|
||||
}
|
||||
|
||||
private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe<ItemStack> recipe) {
|
||||
Object holderOrRecipe = recipeManager.getRecipeHolderByRecipe(recipe);
|
||||
if (holderOrRecipe == null) {
|
||||
// it's a vanilla recipe but not injected
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Object resultInventory = Reflections.field$CraftResultInventory$resultInventory.get(inventory);
|
||||
Reflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
plugin.logger().warn("Failed to correct used recipe", e);
|
||||
}
|
||||
}
|
||||
|
||||
private OptimizedIDItem<ItemStack> getOptimizedIDItem(@Nullable ItemStack itemStack) {
|
||||
if (ItemUtils.isEmpty(itemStack)) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
return idHolder.map(keyReference -> new OptimizedIDItem<>(keyReference, itemStack)).orElse(EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,8 +85,6 @@ public class BukkitInjector {
|
||||
|
||||
public static void init() {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
|
||||
clazz$InjectedCacheChecker = byteBuddy
|
||||
.subclass(Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
|
||||
.implement(Reflections.clazz$RecipeManager$CachedCheck)
|
||||
@@ -349,7 +347,7 @@ public class BukkitInjector {
|
||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
||||
if (!isCustom) {
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, resourceLocation);
|
||||
return optionalRecipe;
|
||||
return Optional.of(pair.getSecond());
|
||||
}
|
||||
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
|
||||
@@ -4125,6 +4125,18 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$CraftSmithingTransformRecipe = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleCBClass("inventory.CraftSmithingTransformRecipe")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$CraftSmithingTransformRecipe$fromBukkitRecipe = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$CraftSmithingTransformRecipe, clazz$CraftSmithingTransformRecipe, SmithingTransformRecipe.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$FeatureFlagSet = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.flag.FeatureFlagSet")
|
||||
@@ -4255,6 +4267,12 @@ public class Reflections {
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeHolder")
|
||||
);
|
||||
|
||||
// 1.20.2-1.21.1 resource location
|
||||
// 1.21.2+ resource key
|
||||
public static final Constructor<?> constructor$RecipeHolder = Optional.ofNullable(clazz$RecipeHolder)
|
||||
.map(it -> ReflectionUtils.getConstructor(it, 0))
|
||||
.orElse(null);
|
||||
|
||||
// 1.20.2+
|
||||
public static final Field field$RecipeHolder$recipe = Optional.ofNullable(clazz$RecipeHolder)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, 1))
|
||||
@@ -4396,6 +4414,18 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$CraftResultInventory = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleCBClass("inventory.CraftResultInventory")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$CraftResultInventory$resultInventory = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$CraftResultInventory, clazz$Container, 0
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20.5+
|
||||
public static final Method method$ItemStack$hurtAndBreak =
|
||||
ReflectionUtils.getMethod(
|
||||
@@ -4933,4 +4963,56 @@ public class Reflections {
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$CraftInventoryAnvil, clazz$AnvilMenu, 0
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$SmithingTransformRecipe = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.SmithingTransformRecipe")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$SmithingTransformRecipe = requireNonNull(
|
||||
VersionHelper.isVersionNewerThan1_21_2() ?
|
||||
ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, Optional.class, Optional.class, clazz$ItemStack) :
|
||||
VersionHelper.isVersionNewerThan1_20_2() ?
|
||||
ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) :
|
||||
ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack)
|
||||
);
|
||||
|
||||
public static final Method method$RecipeManager$addRecipe = requireNonNull(
|
||||
VersionHelper.isVersionNewerThan1_20_2() ?
|
||||
ReflectionUtils.getMethod(clazz$RecipeManager, void.class, clazz$RecipeHolder) :
|
||||
ReflectionUtils.getMethod(clazz$RecipeManager, void.class, clazz$Recipe)
|
||||
);
|
||||
|
||||
public static final Method method$CraftRecipe$toIngredient = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$CraftRecipe, clazz$Ingredient, RecipeChoice.class, boolean.class
|
||||
)
|
||||
);
|
||||
|
||||
// 1.20.5+
|
||||
public static final Method method$ItemStack$transmuteCopy = ReflectionUtils.getMethod(
|
||||
clazz$ItemStack, clazz$ItemStack, clazz$ItemLike, int.class
|
||||
);
|
||||
|
||||
// 1.20.5+
|
||||
public static final Class<?> clazz$DataComponentPatch = ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("core.component.DataComponentPatch")
|
||||
);
|
||||
|
||||
// 1.20.5+
|
||||
public static final Method method$ItemStack$getComponentsPatch = Optional.ofNullable(clazz$DataComponentPatch)
|
||||
.map(it -> ReflectionUtils.getMethod(clazz$ItemStack, it))
|
||||
.orElse(null);
|
||||
|
||||
// 1.20.5+
|
||||
public static final Method method$ItemStack$applyComponents = Optional.ofNullable(clazz$DataComponentPatch)
|
||||
.map(it -> ReflectionUtils.getMethod(clazz$ItemStack, void.class, it))
|
||||
.orElse(null);
|
||||
|
||||
public static final Method method$ItemStack$getItem = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$ItemStack, clazz$Item
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow") version "9.0.0-beta6"
|
||||
id("com.gradleup.shadow") version "9.0.0-beta11"
|
||||
id("maven-publish")
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
|
||||
this.factory.customName(this.item, displayName);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<I> itemName(String itemName) {
|
||||
this.factory.itemName(this.item, itemName);
|
||||
@@ -276,4 +277,10 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
|
||||
public Object getLiteralObject() {
|
||||
return this.item.getLiteralObject();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public Item<I> merge(Item<?> another) {
|
||||
return new AbstractItem<>(this.factory, this.factory.merge(this.item, ((AbstractItem) another).item));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,4 +116,6 @@ public interface Item<I> {
|
||||
boolean is(Key itemTag);
|
||||
|
||||
Object getLiteralObject();
|
||||
|
||||
Item<I> merge(Item<?> another);
|
||||
}
|
||||
|
||||
@@ -108,4 +108,6 @@ public abstract class ItemFactory<P extends Plugin, W extends ItemWrapper<I>, I>
|
||||
protected abstract void repairCost(ItemWrapper<I> item, Integer data);
|
||||
|
||||
protected abstract Optional<Integer> repairCost(ItemWrapper<I> item);
|
||||
|
||||
protected abstract ItemWrapper<I> merge(ItemWrapper<I> item1, ItemWrapper<I> item2);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ItemWrapper<I> {
|
||||
|
||||
I getItem();
|
||||
@@ -37,4 +39,6 @@ public interface ItemWrapper<I> {
|
||||
void count(int amount);
|
||||
|
||||
ItemWrapper<I> copyWithCount(int count);
|
||||
|
||||
Map<String, Object> getData();
|
||||
}
|
||||
|
||||
@@ -4,18 +4,17 @@ import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class AbstractRecipe<T> implements Recipe<T> {
|
||||
public abstract class AbstractGroupedRecipe<T> implements Recipe<T> {
|
||||
protected final String group;
|
||||
protected final Key id;
|
||||
protected final CustomRecipeResult<T> result;
|
||||
|
||||
protected AbstractRecipe(Key id, String group, CustomRecipeResult<T> result) {
|
||||
protected AbstractGroupedRecipe(Key id, String group, CustomRecipeResult<T> result) {
|
||||
this.group = group;
|
||||
this.id = id;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String group() {
|
||||
return group;
|
||||
@@ -21,11 +21,11 @@ public class CustomBlastingRecipe<T> extends CustomCookingRecipe<T> {
|
||||
return RecipeTypes.BLASTING;
|
||||
}
|
||||
|
||||
public static class Factory<A> implements RecipeFactory<CustomBlastingRecipe<A>> {
|
||||
public static class Factory<A> implements RecipeFactory<A> {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"})
|
||||
@Override
|
||||
public Recipe<CustomBlastingRecipe<A>> create(Key id, Map<String, Object> arguments) {
|
||||
public Recipe<A> create(Key id, Map<String, Object> arguments) {
|
||||
CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null;
|
||||
String group = arguments.containsKey("group") ? arguments.get("group").toString() : null;
|
||||
int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80));
|
||||
|
||||
@@ -21,11 +21,11 @@ public class CustomCampfireRecipe<T> extends CustomCookingRecipe<T> {
|
||||
return RecipeTypes.CAMPFIRE_COOKING;
|
||||
}
|
||||
|
||||
public static class Factory<A> implements RecipeFactory<CustomCampfireRecipe<A>> {
|
||||
public static class Factory<A> implements RecipeFactory<A> {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"})
|
||||
@Override
|
||||
public Recipe<CustomCampfireRecipe<A>> create(Key id, Map<String, Object> arguments) {
|
||||
public Recipe<A> create(Key id, Map<String, Object> arguments) {
|
||||
CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null;
|
||||
String group = arguments.containsKey("group") ? arguments.get("group").toString() : null;
|
||||
int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80));
|
||||
|
||||
@@ -6,7 +6,7 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class CustomCookingRecipe<T> extends AbstractRecipe<T> {
|
||||
public abstract class CustomCookingRecipe<T> extends AbstractGroupedRecipe<T> {
|
||||
protected final CookingRecipeCategory category;
|
||||
protected final Ingredient<T> ingredient;
|
||||
protected final float experience;
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public abstract class CustomCraftingTableRecipe<T> extends AbstractRecipe<T> {
|
||||
public abstract class CustomCraftingTableRecipe<T> extends AbstractGroupedRecipe<T> {
|
||||
protected final CraftingRecipeCategory category;
|
||||
|
||||
protected CustomCraftingTableRecipe(Key id, CraftingRecipeCategory category, String group, CustomRecipeResult<T> result) {
|
||||
|
||||
@@ -21,11 +21,11 @@ public class CustomSmeltingRecipe<T> extends CustomCookingRecipe<T> {
|
||||
return RecipeTypes.SMELTING;
|
||||
}
|
||||
|
||||
public static class Factory<A> implements RecipeFactory<CustomSmeltingRecipe<A>> {
|
||||
public static class Factory<A> implements RecipeFactory<A> {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"})
|
||||
@Override
|
||||
public Recipe<CustomSmeltingRecipe<A>> create(Key id, Map<String, Object> arguments) {
|
||||
public Recipe<A> create(Key id, Map<String, Object> arguments) {
|
||||
CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null;
|
||||
String group = arguments.containsKey("group") ? arguments.get("group").toString() : null;
|
||||
int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80));
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
package net.momirealms.craftengine.core.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SmithingInput;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
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.ResourceKey;
|
||||
import net.momirealms.craftengine.core.util.TriConsumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
private final Key id;
|
||||
private final CustomRecipeResult<T> result;
|
||||
private final Ingredient<T> base;
|
||||
private final Ingredient<T> template;
|
||||
private final Ingredient<T> addition;
|
||||
private final boolean mergeComponents;
|
||||
private final List<ItemDataProcessor> processors;
|
||||
|
||||
public CustomSmithingTransformRecipe(Key id,
|
||||
@Nullable Ingredient<T> base,
|
||||
@Nullable Ingredient<T> template,
|
||||
@Nullable Ingredient<T> addition,
|
||||
CustomRecipeResult<T> result,
|
||||
boolean mergeComponents,
|
||||
List<ItemDataProcessor> processors
|
||||
) {
|
||||
this.id = id;
|
||||
this.result = result;
|
||||
this.base = base;
|
||||
this.template = template;
|
||||
this.addition = addition;
|
||||
this.processors = processors;
|
||||
this.mergeComponents = mergeComponents;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean matches(RecipeInput input) {
|
||||
SmithingInput<T> smithingInput = (SmithingInput<T>) input;
|
||||
return checkIngredient(this.base, smithingInput.base())
|
||||
&& checkIngredient(this.template, smithingInput.template())
|
||||
&& checkIngredient(this.addition, smithingInput.addition());
|
||||
}
|
||||
|
||||
private boolean checkIngredient(Ingredient<T> ingredient, OptimizedIDItem<T> item) {
|
||||
if (ingredient != null) {
|
||||
if (item == null || item.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return ingredient.test(item);
|
||||
} else {
|
||||
return item == null || item.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Ingredient<T>> ingredientsInUse() {
|
||||
List<Ingredient<T>> ingredients = new ArrayList<>();
|
||||
ingredients.add(this.base);
|
||||
if (this.template != null) {
|
||||
ingredients.add(this.template);
|
||||
}
|
||||
if (this.addition != null) {
|
||||
ingredients.add(this.addition);
|
||||
}
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Key type() {
|
||||
return RecipeTypes.SMITHING_TRANSFORM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T result(ItemBuildContext context) {
|
||||
return this.result.buildItemStack(context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T assemble(ItemBuildContext context, Item<T> base) {
|
||||
T result = this.result(context);
|
||||
Item<T> wrappedResult = (Item<T>) CraftEngine.instance().itemManager().wrap(result);
|
||||
Item<T> finalResult = wrappedResult;
|
||||
if (this.mergeComponents) {
|
||||
finalResult = base.merge(wrappedResult);
|
||||
}
|
||||
for (ItemDataProcessor processor : this.processors) {
|
||||
processor.accept(base, wrappedResult, finalResult);
|
||||
}
|
||||
return finalResult.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRecipeResult<T> result() {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Ingredient<T> base() {
|
||||
return this.base;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Ingredient<T> template() {
|
||||
return template;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Ingredient<T> addition() {
|
||||
return addition;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"DuplicatedCode"})
|
||||
public static class Factory<A> implements RecipeFactory<A> {
|
||||
|
||||
@Override
|
||||
public Recipe<A> create(Key id, Map<String, Object> arguments) {
|
||||
List<String> base = MiscUtils.getAsStringList(arguments.get("base"));
|
||||
List<String> addition = MiscUtils.getAsStringList(arguments.get("addition"));
|
||||
List<String> template = MiscUtils.getAsStringList(arguments.get("template-type"));
|
||||
boolean mergeComponents = (boolean) arguments.getOrDefault("merge-components", true);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> processors = (List<Map<String, Object>>) arguments.getOrDefault("post-processors", List.of());
|
||||
return new CustomSmithingTransformRecipe<>(
|
||||
id,
|
||||
toIngredient(base), toIngredient(template),toIngredient(addition), parseResult(arguments),
|
||||
mergeComponents,
|
||||
ItemDataProcessors.fromMapList(processors)
|
||||
);
|
||||
}
|
||||
|
||||
private Ingredient<A> toIngredient(List<String> items) {
|
||||
Set<Holder<Key>> holders = new HashSet<>();
|
||||
for (String item : items) {
|
||||
if (item.charAt(0) == '#') {
|
||||
holders.addAll(CraftEngine.instance().itemManager().tagToItems(Key.of(item.substring(1))));
|
||||
} else {
|
||||
holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.of(item)).orElseThrow(() -> new IllegalArgumentException("Invalid vanilla/custom item: " + item)));
|
||||
}
|
||||
}
|
||||
return holders.isEmpty() ? null : Ingredient.of(holders);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ItemDataProcessors {
|
||||
|
||||
public static List<ItemDataProcessor> fromMapList(List<Map<String, Object>> mapList) {
|
||||
if (mapList == null || mapList.isEmpty()) return List.of();
|
||||
List<ItemDataProcessor> functions = new ArrayList<>();
|
||||
for (Map<String, Object> map : mapList) {
|
||||
functions.add(fromMap(map));
|
||||
}
|
||||
return functions;
|
||||
}
|
||||
|
||||
public static ItemDataProcessor fromMap(Map<String, Object> map) {
|
||||
String type = (String) map.get("type");
|
||||
if (type == null) {
|
||||
throw new NullPointerException("processor type cannot be null");
|
||||
}
|
||||
Key key = Key.withDefaultNamespace(type, "craftengine");
|
||||
ItemDataProcessor.Factory factory = BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY.getValue(key);
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Unknown processor type: " + type);
|
||||
}
|
||||
return factory.create(map);
|
||||
}
|
||||
|
||||
public static void register(Key key, ItemDataProcessor.Factory factory) {
|
||||
Holder.Reference<ItemDataProcessor.Factory> holder = ((WritableRegistry<ItemDataProcessor.Factory>) BuiltInRegistries.SMITHING_RESULT_PROCESSOR_FACTORY)
|
||||
.registerForHolder(new ResourceKey<>(Registries.SMITHING_RESULT_PROCESSOR_FACTORY.location(), key));
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ItemDataProcessor extends TriConsumer<Item<?>, Item<?>, Item<?>> {
|
||||
|
||||
interface Factory {
|
||||
ItemDataProcessor create(Map<String, Object> arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,11 @@ public class CustomSmokingRecipe<T> extends CustomCookingRecipe<T> {
|
||||
return RecipeTypes.SMOKING;
|
||||
}
|
||||
|
||||
public static class Factory<A> implements RecipeFactory<CustomSmokingRecipe<A>> {
|
||||
public static class Factory<A> implements RecipeFactory<A> {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "DuplicatedCode"})
|
||||
@Override
|
||||
public Recipe<CustomSmokingRecipe<A>> create(Key id, Map<String, Object> arguments) {
|
||||
public Recipe<A> create(Key id, Map<String, Object> arguments) {
|
||||
CookingRecipeCategory recipeCategory = arguments.containsKey("category") ? CookingRecipeCategory.valueOf(arguments.get("category").toString().toUpperCase(Locale.ENGLISH)) : null;
|
||||
String group = arguments.containsKey("group") ? arguments.get("group").toString() : null;
|
||||
int cookingTime = MiscUtils.getAsInt(arguments.getOrDefault("time", 80));
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CustomStoneCuttingRecipe<T> extends AbstractRecipe<T> {
|
||||
public class CustomStoneCuttingRecipe<T> extends AbstractGroupedRecipe<T> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
protected final Ingredient<T> ingredient;
|
||||
|
||||
@@ -36,7 +36,7 @@ public class CustomStoneCuttingRecipe<T> extends AbstractRecipe<T> {
|
||||
|
||||
@Override
|
||||
public @NotNull Key type() {
|
||||
return RecipeTypes.STONE_CUTTING;
|
||||
return RecipeTypes.STONECUTTING;
|
||||
}
|
||||
|
||||
public Ingredient<T> ingredient() {
|
||||
|
||||
@@ -4,7 +4,6 @@ import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -22,7 +21,4 @@ public interface Recipe<T> {
|
||||
Key type();
|
||||
|
||||
Key id();
|
||||
|
||||
@Nullable
|
||||
String group();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ public class RecipeTypes {
|
||||
public static final Key BLASTING = Key.of("minecraft:blasting");
|
||||
public static final Key SMOKING = Key.of("minecraft:smoking");
|
||||
public static final Key CAMPFIRE_COOKING = Key.of("minecraft:campfire_cooking");
|
||||
public static final Key STONE_CUTTING = Key.of("minecraft:stone_cutting");
|
||||
public static final Key STONECUTTING = Key.of("minecraft:stonecutting");
|
||||
public static final Key SMITHING_TRANSFORM = Key.of("minecraft:smithing_transform");
|
||||
public static final Key SMITHING_TRIM = Key.of("minecraft:smithing_trim");
|
||||
|
||||
static {
|
||||
register(SHAPED, CustomShapedRecipe.FACTORY);
|
||||
@@ -25,7 +27,8 @@ public class RecipeTypes {
|
||||
register(SMOKING, CustomSmokingRecipe.FACTORY);
|
||||
register(BLASTING, CustomBlastingRecipe.FACTORY);
|
||||
register(CAMPFIRE_COOKING, CustomCampfireRecipe.FACTORY);
|
||||
register(STONE_CUTTING, CustomStoneCuttingRecipe.FACTORY);
|
||||
register(STONECUTTING, CustomStoneCuttingRecipe.FACTORY);
|
||||
register(SMITHING_TRANSFORM, CustomSmithingTransformRecipe.FACTORY);
|
||||
}
|
||||
|
||||
public static <T> void register(Key key, RecipeFactory<T> factory) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.input;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SmithingInput<T> implements RecipeInput {
|
||||
private final OptimizedIDItem<T> base;
|
||||
private final OptimizedIDItem<T> template;
|
||||
private final OptimizedIDItem<T> addition;
|
||||
|
||||
public SmithingInput(@Nullable OptimizedIDItem<T> base,
|
||||
@Nullable OptimizedIDItem<T> template,
|
||||
@Nullable OptimizedIDItem<T> addition) {
|
||||
this.base = base;
|
||||
this.template = template;
|
||||
this.addition = addition;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OptimizedIDItem<T> base() {
|
||||
return base;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OptimizedIDItem<T> template() {
|
||||
return template;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OptimizedIDItem<T> addition() {
|
||||
return addition;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -9,4 +11,9 @@ public class VanillaBlastingRecipe extends VanillaCookingRecipe {
|
||||
public VanillaBlastingRecipe(CookingRecipeCategory category, String group, RecipeResult result, List<String> ingredient, float experience, int cookingTime) {
|
||||
super(category, group, result, ingredient, experience, cookingTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.BLASTING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -9,4 +11,9 @@ public class VanillaCampfireRecipe extends VanillaCookingRecipe {
|
||||
public VanillaCampfireRecipe(CookingRecipeCategory category, String group, RecipeResult result, List<String> ingredient, float experience, int cookingTime) {
|
||||
super(category, group, result, ingredient, experience, cookingTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.CAMPFIRE_COOKING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class VanillaCookingRecipe extends VanillaRecipe {
|
||||
public abstract class VanillaCookingRecipe extends VanillaGroupedRecipe {
|
||||
protected final List<String> ingredient;
|
||||
protected final CookingRecipeCategory category;
|
||||
protected final float experience;
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.CraftingRecipeCategory;
|
||||
|
||||
public class VanillaCraftingRecipe extends VanillaRecipe {
|
||||
public abstract class VanillaCraftingRecipe extends VanillaGroupedRecipe {
|
||||
protected final CraftingRecipeCategory category;
|
||||
|
||||
protected VanillaCraftingRecipe(CraftingRecipeCategory category, String group, RecipeResult result) {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
public abstract class VanillaGroupedRecipe implements VanillaRecipe {
|
||||
protected final String group;
|
||||
protected final RecipeResult result;
|
||||
|
||||
protected VanillaGroupedRecipe(String group, RecipeResult result) {
|
||||
this.group = group;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String group() {
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeResult result() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,10 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
public abstract class VanillaRecipe {
|
||||
protected final String group;
|
||||
protected final RecipeResult result;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
protected VanillaRecipe(String group, RecipeResult result) {
|
||||
this.group = group;
|
||||
this.result = result;
|
||||
}
|
||||
public interface VanillaRecipe {
|
||||
|
||||
public String group() {
|
||||
return group;
|
||||
}
|
||||
Key type();
|
||||
|
||||
public RecipeResult result() {
|
||||
return result;
|
||||
}
|
||||
RecipeResult result();
|
||||
}
|
||||
|
||||
@@ -17,4 +17,6 @@ public interface VanillaRecipeReader {
|
||||
VanillaCampfireRecipe readCampfire(JsonObject json);
|
||||
|
||||
VanillaStoneCuttingRecipe readStoneCutting(JsonObject json);
|
||||
|
||||
VanillaSmithingTransformRecipe readSmithingTransform(JsonObject json);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.CraftingRecipeCategory;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -26,4 +28,9 @@ public class VanillaShapedRecipe extends VanillaCraftingRecipe {
|
||||
public String[] pattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.SHAPED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.CraftingRecipeCategory;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -15,4 +17,9 @@ public class VanillaShapelessRecipe extends VanillaCraftingRecipe {
|
||||
public List<List<String>> ingredients() {
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.SHAPELESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -9,4 +11,9 @@ public class VanillaSmeltingRecipe extends VanillaCookingRecipe {
|
||||
public VanillaSmeltingRecipe(CookingRecipeCategory category, String group, RecipeResult result, List<String> ingredient, float experience, int cookingTime) {
|
||||
super(category, group, result, ingredient, experience, cookingTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.SMELTING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VanillaSmithingTransformRecipe implements VanillaRecipe {
|
||||
private final RecipeResult result;
|
||||
private final List<String> base;
|
||||
private final List<String> template;
|
||||
private final List<String> addition;
|
||||
|
||||
public VanillaSmithingTransformRecipe(List<String> base, List<String> template, List<String> addition, RecipeResult result) {
|
||||
this.result = result;
|
||||
this.base = base;
|
||||
this.template = template;
|
||||
this.addition = addition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.SMITHING_TRANSFORM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeResult result() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<String> base() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public List<String> template() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public List<String> addition() {
|
||||
return addition;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.CookingRecipeCategory;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -9,4 +11,9 @@ public class VanillaSmokingRecipe extends VanillaCookingRecipe {
|
||||
public VanillaSmokingRecipe(CookingRecipeCategory category, String group, RecipeResult result, List<String> ingredient, float experience, int cookingTime) {
|
||||
super(category, group, result, ingredient, experience, cookingTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.SMOKING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package net.momirealms.craftengine.core.item.recipe.vanilla;
|
||||
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VanillaStoneCuttingRecipe extends VanillaRecipe {
|
||||
public class VanillaStoneCuttingRecipe extends VanillaGroupedRecipe {
|
||||
private final List<String> ingredient;
|
||||
|
||||
public VanillaStoneCuttingRecipe(String group, RecipeResult result, List<String> ingredient) {
|
||||
@@ -13,4 +16,9 @@ public class VanillaStoneCuttingRecipe extends VanillaRecipe {
|
||||
public List<String> ingredient() {
|
||||
return ingredient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return RecipeTypes.STONECUTTING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,16 @@ public class VanillaRecipeReader1_20 extends AbstractRecipeReader {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VanillaSmithingTransformRecipe readSmithingTransform(JsonObject json) {
|
||||
return new VanillaSmithingTransformRecipe(
|
||||
readSingleIngredient(json.get("base")),
|
||||
readSingleIngredient(json.get("template")),
|
||||
readSingleIngredient(json.get("addition")),
|
||||
readSmithingResult(json.getAsJsonObject("result"))
|
||||
);
|
||||
}
|
||||
|
||||
protected List<String> readSingleIngredient(JsonElement json) {
|
||||
List<String> ingredients = new ArrayList<>();
|
||||
if (json.isJsonObject()) {
|
||||
@@ -126,6 +136,12 @@ public class VanillaRecipeReader1_20 extends AbstractRecipeReader {
|
||||
return new RecipeResult(item, count, null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected RecipeResult readSmithingResult(JsonObject object) {
|
||||
String item = object.get("item").getAsString();
|
||||
return new RecipeResult(item, 1, null);
|
||||
}
|
||||
|
||||
protected List<List<String>> readShapelessIngredients(JsonArray json) {
|
||||
List<List<String>> ingredients = new ArrayList<>();
|
||||
for (JsonElement element : json) {
|
||||
|
||||
@@ -26,4 +26,9 @@ public class VanillaRecipeReader1_20_5 extends VanillaRecipeReader1_20 {
|
||||
protected RecipeResult readStoneCuttingResult(JsonObject json) {
|
||||
return readCraftingResult(json.getAsJsonObject("result"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull RecipeResult readSmithingResult(JsonObject object) {
|
||||
return readCraftingResult(object.getAsJsonObject());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class NumberProviders {
|
||||
holder.bindValue(factory);
|
||||
}
|
||||
|
||||
static List<NumberProvider> fromMapList(List<Map<String, Object>> mapList) {
|
||||
public static List<NumberProvider> fromMapList(List<Map<String, Object>> mapList) {
|
||||
if (mapList == null || mapList.isEmpty()) return List.of();
|
||||
List<NumberProvider> functions = new ArrayList<>();
|
||||
for (Map<String, Object> map : mapList) {
|
||||
|
||||
@@ -249,6 +249,7 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smelting.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/campfire.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/cooking_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/crafting_recipe.png");
|
||||
plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/no_recipe.png");
|
||||
|
||||
@@ -54,6 +54,7 @@ public class ConfigManager implements Reloadable {
|
||||
protected long resource_pack$protection$obfuscation$seed;
|
||||
protected boolean resource_pack$protection$obfuscation$fake_directory;
|
||||
protected boolean resource_pack$protection$obfuscation$escape_unicode;
|
||||
protected boolean resource_pack$protection$obfuscation$break_json;
|
||||
protected boolean resource_pack$protection$obfuscation$resource_location$enable;
|
||||
protected int resource_pack$protection$obfuscation$resource_location$random_namespace$length;
|
||||
protected int resource_pack$protection$obfuscation$resource_location$random_namespace$amount;
|
||||
@@ -200,6 +201,7 @@ public class ConfigManager implements Reloadable {
|
||||
resource_pack$protection$obfuscation$seed = config.getLong("resource-pack.protection.obfuscation.seed", 0L);
|
||||
resource_pack$protection$obfuscation$fake_directory = config.getBoolean("resource-pack.protection.obfuscation.fake-directory", false);
|
||||
resource_pack$protection$obfuscation$escape_unicode = config.getBoolean("resource-pack.protection.obfuscation.escape-unicode", false);
|
||||
resource_pack$protection$obfuscation$break_json = config.getBoolean("resource-pack.protection.obfuscation.break-json", false);
|
||||
|
||||
resource_pack$protection$obfuscation$resource_location$enable = config.getBoolean("resource-pack.protection.obfuscation.resource-location.enable", false);
|
||||
resource_pack$protection$obfuscation$resource_location$random_namespace$amount = config.getInt("resource-pack.protection.obfuscation.resource-location.random-namespace.amount", 32);
|
||||
@@ -435,6 +437,10 @@ public class ConfigManager implements Reloadable {
|
||||
return instance.resource_pack$protection$obfuscation$escape_unicode;
|
||||
}
|
||||
|
||||
public static boolean breakJson() {
|
||||
return instance.resource_pack$protection$obfuscation$break_json;
|
||||
}
|
||||
|
||||
public static boolean enableRandomResourceLocation() {
|
||||
return instance.resource_pack$protection$obfuscation$resource_location$enable;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser {
|
||||
public static String RECIPE_CAMPFIRE_TITLE;
|
||||
public static String RECIPE_CRAFTING_TITLE;
|
||||
public static String RECIPE_STONECUTTING_TITLE;
|
||||
public static String RECIPE_SMITHING_TRANSFORM_TITLE;
|
||||
public static Key RECIPE_BACK;
|
||||
public static Key RECIPE_EXIT;
|
||||
public static Key RECIPE_NEXT_PAGE_AVAILABLE;
|
||||
@@ -100,9 +101,10 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser {
|
||||
RECIPE_BLASTING_TITLE = getOrThrow(section, "recipe.blasting.title");
|
||||
RECIPE_SMELTING_TITLE = getOrThrow(section, "recipe.smelting.title");
|
||||
RECIPE_SMOKING_TITLE = getOrThrow(section, "recipe.smoking.title");
|
||||
RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire.title");
|
||||
RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire-cooking.title");
|
||||
RECIPE_CRAFTING_TITLE = getOrThrow(section, "recipe.crafting.title");
|
||||
RECIPE_STONECUTTING_TITLE = getOrThrow(section, "recipe.stonecutting.title");
|
||||
RECIPE_SMITHING_TRANSFORM_TITLE = getOrThrow(section, "recipe.smithing-transform.title");
|
||||
RECIPE_BACK = Key.of(getOrThrow(section, "recipe.page-navigation.return"));
|
||||
RECIPE_EXIT = Key.of(getOrThrow(section, "recipe.page-navigation.exit"));
|
||||
RECIPE_NEXT_PAGE_AVAILABLE = Key.of(getOrThrow(section, "recipe.page-navigation.next.available"));
|
||||
|
||||
@@ -349,10 +349,215 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager {
|
||||
openCookingRecipePage(player, (CustomCookingRecipe<Object>) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage);
|
||||
return;
|
||||
}
|
||||
if (recipeType == RecipeTypes.STONE_CUTTING) {
|
||||
if (recipeType == RecipeTypes.STONECUTTING) {
|
||||
openStoneCuttingRecipePage(player, (CustomStoneCuttingRecipe<Object>) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage);
|
||||
return;
|
||||
}
|
||||
if (recipeType == RecipeTypes.SMITHING_TRANSFORM) {
|
||||
openSmithingTransformRecipePage(player, (CustomSmithingTransformRecipe<Object>) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void openSmithingTransformRecipePage(Player player, CustomSmithingTransformRecipe<Object> recipe, Gui parentGui, List<Recipe<Object>> recipes, int index, int depth, boolean canOpenNoRecipePage) {
|
||||
Key previous = index > 0 ? Constants.RECIPE_PREVIOUS_PAGE_AVAILABLE : Constants.RECIPE_PREVIOUS_PAGE_BLOCK;
|
||||
Key next = index + 1 < recipes.size() ? Constants.RECIPE_NEXT_PAGE_AVAILABLE : Constants.RECIPE_NEXT_PAGE_BLOCK;
|
||||
Key result = recipe.result().item().id();
|
||||
GuiLayout layout = new GuiLayout(
|
||||
" ",
|
||||
" ",
|
||||
" ABC X ",
|
||||
" ^ ",
|
||||
" ",
|
||||
" < = > "
|
||||
)
|
||||
.addIngredient('X', GuiElement.constant(this.plugin.itemManager().createWrappedItem(result, player).count(recipe.result().count()), (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(result, player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(result);
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, result, e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(result);
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}))
|
||||
.addIngredient('^', player.hasPermission(GET_ITEM_PERMISSION) ? GuiElement.constant(this.plugin.itemManager().createWrappedItem(Constants.RECIPE_GET_ITEM, player), (e, c) -> {
|
||||
c.cancel();
|
||||
player.playSound(Constants.SOUND_PICK_ITEM);
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
player.giveItem(this.plugin.itemManager().createWrappedItem(result, player));
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(result, player);
|
||||
player.giveItem(item.count(item.maxStackSize()));
|
||||
}
|
||||
}) : GuiElement.EMPTY)
|
||||
.addIngredient('=', GuiElement.constant(this.plugin.itemManager().getCustomItem(parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT)
|
||||
.map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.EMPTY)))
|
||||
.orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + (parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT))),
|
||||
((element, click) -> {
|
||||
click.cancel();
|
||||
player.playSound(Constants.SOUND_RETURN_PAGE, 0.25f, 1);
|
||||
if (parentGui != null) {
|
||||
parentGui.open(player);
|
||||
} else {
|
||||
player.closeInventory();
|
||||
}
|
||||
}))
|
||||
)
|
||||
.addIngredient('>', GuiElement.constant(this.plugin.itemManager()
|
||||
.getCustomItem(next)
|
||||
.map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder()
|
||||
.withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1))
|
||||
.withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size()))
|
||||
.build())))
|
||||
.orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + next)), (e, c) -> {
|
||||
c.cancel();
|
||||
if (index + 1 < recipes.size()) {
|
||||
player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1);
|
||||
openRecipePage(player, parentGui, recipes, index + 1, depth, canOpenNoRecipePage);
|
||||
}
|
||||
}))
|
||||
.addIngredient('<', GuiElement.constant(this.plugin.itemManager()
|
||||
.getCustomItem(previous)
|
||||
.map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder()
|
||||
.withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1))
|
||||
.withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size()))
|
||||
.build())))
|
||||
.orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + previous)), (e, c) -> {
|
||||
c.cancel();
|
||||
if (index > 0) {
|
||||
player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1);
|
||||
openRecipePage(player, parentGui, recipes, index - 1, depth, canOpenNoRecipePage);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
List<Item<?>> templates = new ArrayList<>();
|
||||
Optional.ofNullable(recipe.template()).ifPresent(it -> {
|
||||
for (Holder<Key> in : it.items()) {
|
||||
templates.add(this.plugin.itemManager().createWrappedItem(in.value(), player));
|
||||
}
|
||||
});
|
||||
layout.addIngredient('A', templates.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(templates, (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(e.item().id(), player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
List<Item<?>> bases = new ArrayList<>();
|
||||
Optional.ofNullable(recipe.base()).ifPresent(it -> {
|
||||
for (Holder<Key> in : it.items()) {
|
||||
bases.add(this.plugin.itemManager().createWrappedItem(in.value(), player));
|
||||
}
|
||||
});
|
||||
layout.addIngredient('B', bases.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(bases, (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(e.item().id(), player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
List<Item<?>> additions = new ArrayList<>();
|
||||
Optional.ofNullable(recipe.addition()).ifPresent(it -> {
|
||||
for (Holder<Key> in : it.items()) {
|
||||
additions.add(this.plugin.itemManager().createWrappedItem(in.value(), player));
|
||||
}
|
||||
});
|
||||
layout.addIngredient('C', additions.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(additions, (e, c) -> {
|
||||
c.cancel();
|
||||
if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) {
|
||||
Item<?> item = this.plugin.itemManager().createWrappedItem(e.item().id(), player);
|
||||
item.count(item.maxStackSize());
|
||||
c.setItemOnCursor(item);
|
||||
return;
|
||||
}
|
||||
if (LEFT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
} else if (canOpenNoRecipePage) {
|
||||
openNoRecipePage(player, e.item().id(), e.gui(), 0);
|
||||
}
|
||||
} else if (RIGHT_CLICK.contains(c.type())) {
|
||||
List<Recipe<Object>> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id());
|
||||
if (inRecipes == recipes) return;
|
||||
player.playSound(Constants.SOUND_CLICK_BUTTON);
|
||||
if (!inRecipes.isEmpty()) {
|
||||
openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
BasicGui.builder()
|
||||
.layout(layout)
|
||||
.inventoryClickConsumer(c -> {
|
||||
if (MOVE_TO_OTHER_INV.contains(c.type()) || DOUBLE_CLICK.contains(c.type())) {
|
||||
c.cancel();
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_SMITHING_TRANSFORM_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers()))
|
||||
.refresh()
|
||||
.open(player);
|
||||
}
|
||||
|
||||
public void openStoneCuttingRecipePage(Player player, CustomStoneCuttingRecipe<Object> recipe, Gui parentGui, List<Recipe<Object>> recipes, int index, int depth, boolean canOpenNoRecipePage) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditionFactory;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory;
|
||||
@@ -43,6 +44,7 @@ public class BuiltInRegistries {
|
||||
public static final Registry<ApplyBonusCountFunction.FormulaFactory> FORMULA_FACTORY = createRegistry(Registries.FORMULA_FACTORY);
|
||||
public static final Registry<PathMatcherFactory> PATH_MATCHER_FACTORY = createRegistry(Registries.PATH_MATCHER_FACTORY);
|
||||
public static final Registry<ResolutionFactory> RESOLUTION_FACTORY = createRegistry(Registries.RESOLUTION_FACTORY);
|
||||
public static final Registry<CustomSmithingTransformRecipe.ItemDataProcessor.Factory> SMITHING_RESULT_PROCESSOR_FACTORY = createRegistry(Registries.SMITHING_RESULT_PROCESSOR_FACTORY);
|
||||
|
||||
private static <T> Registry<T> createRegistry(ResourceKey<? extends Registry<T>> key) {
|
||||
return new MappedRegistry<>(key);
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.PropertyFactory;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomSmithingTransformRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeFactory;
|
||||
import net.momirealms.craftengine.core.loot.condition.LootConditionFactory;
|
||||
import net.momirealms.craftengine.core.loot.entry.LootEntryContainerFactory;
|
||||
@@ -44,4 +45,5 @@ public class Registries {
|
||||
public static final ResourceKey<Registry<ApplyBonusCountFunction.FormulaFactory>> FORMULA_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("formula_factory"));
|
||||
public static final ResourceKey<Registry<PathMatcherFactory>> PATH_MATCHER_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("path_matcher_factory"));
|
||||
public static final ResourceKey<Registry<ResolutionFactory>> RESOLUTION_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("resolution_factory"));
|
||||
public static final ResourceKey<Registry<CustomSmithingTransformRecipe.ItemDataProcessor.Factory>> SMITHING_RESULT_PROCESSOR_FACTORY = new ResourceKey<>(ROOT_REGISTRY, Key.withDefaultNamespace("smithing_result_processor_factory"));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=0.0.34
|
||||
config_version=14
|
||||
project_version=0.0.35
|
||||
config_version=15
|
||||
lang_version=3
|
||||
project_group=net.momirealms
|
||||
latest_minecraft_version=1.21.4
|
||||
@@ -38,7 +38,7 @@ geantyref_version=1.3.16
|
||||
zstd_version=1.5.6-9
|
||||
commons_io_version=2.17.0
|
||||
sparrow_nbt_version=0.3
|
||||
sparrow_util_version=0.22
|
||||
sparrow_util_version=0.29
|
||||
fastutil_version=8.5.15
|
||||
netty_version=4.1.119.Final
|
||||
joml_version=1.10.8
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id("java-library")
|
||||
id("com.gradleup.shadow") version "9.0.0-beta6"
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.14"
|
||||
id("com.gradleup.shadow") version "9.0.0-beta11"
|
||||
id("io.papermc.paperweight.userdev") version "2.0.0-beta.16"
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
||||
@@ -9,5 +9,9 @@ pluginManagement {
|
||||
plugins {
|
||||
kotlin("jvm") version "2.0.20"
|
||||
}
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user