mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-08 14:36:44 +01:00
Expand on spell crafting
This commit is contained in:
parent
7949ccff2e
commit
338491d052
8 changed files with 298 additions and 42 deletions
|
@ -0,0 +1,71 @@
|
||||||
|
package com.minelittlepony.unicopia.ability.magic.spell.crafting;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
|
import com.minelittlepony.unicopia.item.GemstoneItem;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.recipe.Ingredient;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.JsonHelper;
|
||||||
|
|
||||||
|
public class IngredientWithSpell implements Predicate<ItemStack> {
|
||||||
|
|
||||||
|
private Optional<Ingredient> stack = Optional.empty();
|
||||||
|
private Optional<SpellType<?>> spell = Optional.empty();
|
||||||
|
|
||||||
|
private IngredientWithSpell() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(ItemStack t) {
|
||||||
|
boolean stackMatch = stack.map(m -> m.test(t)).orElse(true);
|
||||||
|
boolean spellMatch = spell.map(m -> GemstoneItem.getSpellKey(t).equals(m)).orElse(true);
|
||||||
|
return stackMatch && spellMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(PacketByteBuf buf) {
|
||||||
|
stack.ifPresentOrElse(i -> {
|
||||||
|
buf.writeBoolean(true);
|
||||||
|
i.write(buf);
|
||||||
|
}, () -> buf.writeBoolean(false));
|
||||||
|
spell.ifPresentOrElse(i -> {
|
||||||
|
buf.writeBoolean(true);
|
||||||
|
buf.writeIdentifier(i.getId());
|
||||||
|
}, () -> buf.writeBoolean(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IngredientWithSpell fromPacket(PacketByteBuf buf) {
|
||||||
|
IngredientWithSpell ingredient = new IngredientWithSpell();
|
||||||
|
|
||||||
|
if (buf.readBoolean()) {
|
||||||
|
ingredient.stack = Optional.ofNullable(Ingredient.fromPacket(buf));
|
||||||
|
}
|
||||||
|
if (buf.readBoolean()) {
|
||||||
|
ingredient.spell = Optional.of(SpellType.getKey(buf.readIdentifier()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IngredientWithSpell fromJson(JsonObject json) {
|
||||||
|
|
||||||
|
IngredientWithSpell ingredient = new IngredientWithSpell();
|
||||||
|
|
||||||
|
if (json.has("item") || json.has("spell")) {
|
||||||
|
if (json.has("item")) {
|
||||||
|
ingredient.stack = Optional.ofNullable(Ingredient.fromJson(JsonHelper.getObject(json, "item")));
|
||||||
|
}
|
||||||
|
if (json.has("spell")) {
|
||||||
|
ingredient.spell = Optional.ofNullable(Identifier.tryParse(JsonHelper.getString(json, "spell"))).map(SpellType::getKey);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ingredient.stack = Optional.ofNullable(Ingredient.fromJson(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingredient;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.minelittlepony.unicopia.ability.magic.spell.crafting;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
|
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.util.JsonHelper;
|
||||||
|
|
||||||
|
public class TraitIngredient implements Predicate<SpellTraits> {
|
||||||
|
|
||||||
|
private Optional<SpellTraits> min = Optional.empty();
|
||||||
|
private Optional<SpellTraits> max = Optional.empty();
|
||||||
|
|
||||||
|
private TraitIngredient() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(SpellTraits t) {
|
||||||
|
boolean minMatch = min.map(m -> t.includes(m)).orElse(true);
|
||||||
|
boolean maxMatch = max.map(m -> m.includes(t)).orElse(true);
|
||||||
|
return minMatch && maxMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(PacketByteBuf buf) {
|
||||||
|
min.ifPresentOrElse(m -> {
|
||||||
|
buf.writeBoolean(true);
|
||||||
|
m.write(buf);
|
||||||
|
}, () -> buf.writeBoolean(false));
|
||||||
|
max.ifPresentOrElse(m -> {
|
||||||
|
buf.writeBoolean(true);
|
||||||
|
m.write(buf);
|
||||||
|
}, () -> buf.writeBoolean(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TraitIngredient fromPacket(PacketByteBuf buf) {
|
||||||
|
TraitIngredient ingredient = new TraitIngredient();
|
||||||
|
|
||||||
|
if (buf.readBoolean()) {
|
||||||
|
ingredient.min = SpellTraits.fromPacket(buf);
|
||||||
|
}
|
||||||
|
if (buf.readBoolean()) {
|
||||||
|
ingredient.max = SpellTraits.fromPacket(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TraitIngredient fromJson(JsonObject json) {
|
||||||
|
|
||||||
|
TraitIngredient ingredient = new TraitIngredient();
|
||||||
|
|
||||||
|
if (json.has("min") || json.has("max")) {
|
||||||
|
if (json.has("min")) {
|
||||||
|
ingredient.min = SpellTraits.fromJson(JsonHelper.getObject(json, "min"));
|
||||||
|
}
|
||||||
|
if (json.has("max")) {
|
||||||
|
ingredient.max = SpellTraits.fromJson(JsonHelper.getObject(json, "max"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ingredient.min = SpellTraits.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingredient;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@ import com.minelittlepony.unicopia.item.URecipes;
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.recipe.Ingredient;
|
|
||||||
import net.minecraft.recipe.RecipeSerializer;
|
import net.minecraft.recipe.RecipeSerializer;
|
||||||
import net.minecraft.recipe.ShapedRecipe;
|
import net.minecraft.recipe.ShapedRecipe;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
@ -17,13 +16,12 @@ import net.minecraft.util.JsonHelper;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class TraitRequirementRecipe implements SpellbookRecipe {
|
public class TraitRequirementRecipe implements SpellbookRecipe {
|
||||||
|
|
||||||
private final Identifier id;
|
private final Identifier id;
|
||||||
private final Ingredient requirement;
|
private final IngredientWithSpell requirement;
|
||||||
private final SpellTraits requiredTraits;
|
private final TraitIngredient requiredTraits;
|
||||||
private final ItemStack output;
|
private final ItemStack output;
|
||||||
|
|
||||||
private TraitRequirementRecipe(Identifier id, Ingredient requirement, SpellTraits requiredTraits, ItemStack output) {
|
private TraitRequirementRecipe(Identifier id, IngredientWithSpell requirement, TraitIngredient requiredTraits, ItemStack output) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.requirement = requirement;
|
this.requirement = requirement;
|
||||||
this.requiredTraits = requiredTraits;
|
this.requiredTraits = requiredTraits;
|
||||||
|
@ -33,14 +31,18 @@ public class TraitRequirementRecipe implements SpellbookRecipe {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(SpellbookInventory inventory, World world) {
|
public boolean matches(SpellbookInventory inventory, World world) {
|
||||||
return requirement.test(inventory.getItemToModify())
|
return requirement.test(inventory.getItemToModify())
|
||||||
&& SpellTraits.of(inventory).includes(requiredTraits);
|
&& requiredTraits.test(SpellTraits.union(
|
||||||
|
SpellTraits.of(inventory.getItemToModify()),
|
||||||
|
inventory.getTraits(),
|
||||||
|
SpellTraits.of(output)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack craft(SpellbookInventory inventory) {
|
public ItemStack craft(SpellbookInventory inventory) {
|
||||||
return SpellTraits.union(
|
return SpellTraits.union(
|
||||||
SpellTraits.of(inventory.getItemToModify()),
|
SpellTraits.of(inventory.getItemToModify()),
|
||||||
SpellTraits.of(inventory),
|
inventory.getTraits(),
|
||||||
SpellTraits.of(output)
|
SpellTraits.of(output)
|
||||||
).applyTo(output);
|
).applyTo(output);
|
||||||
}
|
}
|
||||||
|
@ -81,16 +83,16 @@ public class TraitRequirementRecipe implements SpellbookRecipe {
|
||||||
@Override
|
@Override
|
||||||
public TraitRequirementRecipe read(Identifier id, JsonObject json) {
|
public TraitRequirementRecipe read(Identifier id, JsonObject json) {
|
||||||
return new TraitRequirementRecipe(id,
|
return new TraitRequirementRecipe(id,
|
||||||
Ingredient.fromJson(JsonHelper.getObject(json, "material")),
|
IngredientWithSpell.fromJson(JsonHelper.getObject(json, "material")),
|
||||||
SpellTraits.fromJson(JsonHelper.getObject(json, "traits")).get(),
|
TraitIngredient.fromJson(JsonHelper.getObject(json, "traits")),
|
||||||
outputFromJson(JsonHelper.getObject(json, "result")));
|
outputFromJson(JsonHelper.getObject(json, "result")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TraitRequirementRecipe read(Identifier id, PacketByteBuf buf) {
|
public TraitRequirementRecipe read(Identifier id, PacketByteBuf buf) {
|
||||||
return new TraitRequirementRecipe(id,
|
return new TraitRequirementRecipe(id,
|
||||||
Ingredient.fromPacket(buf),
|
IngredientWithSpell.fromPacket(buf),
|
||||||
SpellTraits.fromPacket(buf).get(),
|
TraitIngredient.fromPacket(buf),
|
||||||
buf.readItemStack()
|
buf.readItemStack()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,14 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -26,7 +29,7 @@ import net.minecraft.text.LiteralText;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.registry.Registry;
|
import net.minecraft.util.registry.Registry;
|
||||||
|
|
||||||
public final class SpellTraits {
|
public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
|
||||||
public static final SpellTraits EMPTY = new SpellTraits(Map.of());
|
public static final SpellTraits EMPTY = new SpellTraits(Map.of());
|
||||||
|
|
||||||
private final Map<Trait, Float> traits;
|
private final Map<Trait, Float> traits;
|
||||||
|
@ -35,20 +38,47 @@ public final class SpellTraits {
|
||||||
this.traits = traits;
|
this.traits = traits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpellTraits(SpellTraits from) {
|
||||||
|
this(new EnumMap<>(from.traits));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpellTraits multiply(float factor) {
|
||||||
|
return factor == 0 ? EMPTY : map(v -> v * factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpellTraits map(Function<Float, Float> function) {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Trait, Float> newMap = new EnumMap<>(traits);
|
||||||
|
newMap.entrySet().forEach(entry -> entry.setValue(function.apply(entry.getValue())));
|
||||||
|
return fromEntries(newMap.entrySet().stream()).orElse(EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return traits.isEmpty();
|
return traits.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean includes(SpellTraits other) {
|
public boolean includes(SpellTraits other) {
|
||||||
return other.entries().stream().allMatch(pair -> {
|
return other.stream().allMatch(pair -> {
|
||||||
return getAmount(pair.getKey()) >= pair.getValue();
|
return getAmount(pair.getKey()) >= pair.getValue();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Entry<Trait, Float>> iterator() {
|
||||||
|
return entries().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
public Set<Map.Entry<Trait, Float>> entries() {
|
public Set<Map.Entry<Trait, Float>> entries() {
|
||||||
return traits.entrySet();
|
return traits.entrySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream<Map.Entry<Trait, Float>> stream() {
|
||||||
|
return entries().stream();
|
||||||
|
}
|
||||||
|
|
||||||
public float getAmount(Trait trait) {
|
public float getAmount(Trait trait) {
|
||||||
return traits.getOrDefault(trait, 0F);
|
return traits.getOrDefault(trait, 0F);
|
||||||
}
|
}
|
||||||
|
@ -179,12 +209,15 @@ public final class SpellTraits {
|
||||||
|
|
||||||
static void combine(Map<Trait, Float> to, Map<Trait, Float> from) {
|
static void combine(Map<Trait, Float> to, Map<Trait, Float> from) {
|
||||||
from.forEach((trait, value) -> {
|
from.forEach((trait, value) -> {
|
||||||
|
if (value != 0) {
|
||||||
to.compute(trait, (k, v) -> v == null ? value : (v + value));
|
to.compute(trait, (k, v) -> v == null ? value : (v + value));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<Trait, Float> collect(Stream<Map.Entry<Trait, Float>> entries) {
|
static Map<Trait, Float> collect(Stream<Map.Entry<Trait, Float>> entries) {
|
||||||
return entries.filter(Objects::nonNull)
|
return entries.filter(Objects::nonNull)
|
||||||
|
.filter(e -> e.getValue() != 0)
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a + b, () -> new EnumMap<>(Trait.class)));
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a + b, () -> new EnumMap<>(Trait.class)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ public class SpellbookScreen extends HandledScreen<SpellbookScreenHandler> {
|
||||||
for (Slot slot : handler.slots) {
|
for (Slot slot : handler.slots) {
|
||||||
if (slot.isEnabled() && slot instanceof SpellbookSlot) {
|
if (slot.isEnabled() && slot instanceof SpellbookSlot) {
|
||||||
drawTexture(matrices, slot.x - 1, slot.y - 1, 74, 223, 18, 18, 512, 256);
|
drawTexture(matrices, slot.x - 1, slot.y - 1, 74, 223, 18, 18, 512, 256);
|
||||||
|
// drawStringWithShadow(matrices, this.textRenderer, ((SpellbookSlot)slot).getRing() + "", slot.x, slot.y, 0x000000FF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RenderSystem.disableBlend();
|
RenderSystem.disableBlend();
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.item.UItems;
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
import com.minelittlepony.unicopia.item.URecipes;
|
import com.minelittlepony.unicopia.item.URecipes;
|
||||||
|
@ -18,14 +19,13 @@ import net.minecraft.inventory.Inventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
|
||||||
import net.minecraft.screen.ScreenHandler;
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext;
|
||||||
import net.minecraft.screen.slot.CraftingResultSlot;
|
import net.minecraft.screen.slot.CraftingResultSlot;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvents;
|
import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.util.Pair;
|
|
||||||
import net.minecraft.util.collection.DefaultedList;
|
import net.minecraft.util.collection.DefaultedList;
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
public class SpellbookScreenHandler extends ScreenHandler {
|
public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
|
|
||||||
|
@ -42,12 +42,19 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
|
|
||||||
private final PlayerInventory inventory;
|
private final PlayerInventory inventory;
|
||||||
|
|
||||||
|
private final ScreenHandlerContext context;
|
||||||
|
|
||||||
protected SpellbookScreenHandler(int syncId, PlayerInventory inv) {
|
protected SpellbookScreenHandler(int syncId, PlayerInventory inv) {
|
||||||
|
this(syncId, inv, ScreenHandlerContext.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpellbookScreenHandler(int syncId, PlayerInventory inv, ScreenHandlerContext context) {
|
||||||
super(UScreenHandlers.SPELL_BOOK, syncId);
|
super(UScreenHandlers.SPELL_BOOK, syncId);
|
||||||
inventory = inv;
|
inventory = inv;
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
List<Pair<Integer, Integer>> grid = new ArrayList<>();
|
List<int[]> grid = new ArrayList<>();
|
||||||
List<Pair<Integer, Integer>> gemPos = new ArrayList<>();
|
List<int[]> gemPos = new ArrayList<>();
|
||||||
createGrid(grid, gemPos);
|
createGrid(grid, gemPos);
|
||||||
|
|
||||||
GEM_SLOT_INDEX = MAX_INGREDIENTS = grid.size();
|
GEM_SLOT_INDEX = MAX_INGREDIENTS = grid.size();
|
||||||
|
@ -58,10 +65,10 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
|
|
||||||
for (int i = 0; i < MAX_INGREDIENTS; i++) {
|
for (int i = 0; i < MAX_INGREDIENTS; i++) {
|
||||||
var pos = grid.get(i);
|
var pos = grid.get(i);
|
||||||
addSlot(new InputSlot(input, i, pos.getLeft(), pos.getRight()));
|
addSlot(new InputSlot(input, i, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
addSlot(gemSlot = new OutputSlot(inventory.player, input, result, 0, gemPos.get(0).getLeft(), gemPos.get(0).getRight()));
|
addSlot(gemSlot = new OutputSlot(inventory.player, input, result, 0, gemPos.get(0)));
|
||||||
|
|
||||||
for (int i = 0; i < 9; ++i) {
|
for (int i = 0; i < 9; ++i) {
|
||||||
addSlot(new Slot(inventory, i, 121 + i * 18, 195));
|
addSlot(new Slot(inventory, i, 121 + i * 18, 195));
|
||||||
|
@ -77,16 +84,16 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContentChanged(Inventory inventory) {
|
public void onContentChanged(Inventory inventory) {
|
||||||
World world = this.inventory.player.world;
|
context.run((world, pos) -> {
|
||||||
if (!world.isClient && !gemSlot.getStack().isEmpty()) {
|
if (!world.isClient && !gemSlot.getStack().isEmpty()) {
|
||||||
world.getServer().getRecipeManager().getFirstMatch(URecipes.SPELLBOOK, input, world)
|
world.getServer().getRecipeManager().getFirstMatch(URecipes.SPELLBOOK, input, world)
|
||||||
.filter(recipe -> result.shouldCraftRecipe(world, (ServerPlayerEntity)this.inventory.player, recipe))
|
.filter(recipe -> result.shouldCraftRecipe(world, (ServerPlayerEntity)this.inventory.player, recipe))
|
||||||
.map(recipe -> {
|
.map(recipe -> recipe.craft(input))
|
||||||
this.inventory.player.playSound(SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.MASTER, 1, 0.3F);
|
|
||||||
return recipe.craft(input);
|
|
||||||
})
|
|
||||||
.ifPresentOrElse(gemSlot::setCrafted, gemSlot::setUncrafted);
|
.ifPresentOrElse(gemSlot::setCrafted, gemSlot::setUncrafted);
|
||||||
|
|
||||||
|
((ServerPlayerEntity)this.inventory.player).networkHandler.sendPacket(new ScreenHandlerSlotUpdateS2CPacket(syncId, GEM_SLOT_INDEX, gemSlot.getStack()));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -190,11 +197,18 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
public void close(PlayerEntity playerEntity) {
|
public void close(PlayerEntity playerEntity) {
|
||||||
gemSlot.setUncrafted();
|
gemSlot.setUncrafted();
|
||||||
super.close(playerEntity);
|
super.close(playerEntity);
|
||||||
|
context.run((world, pos) -> {
|
||||||
dropInventory(playerEntity, input);
|
dropInventory(playerEntity, input);
|
||||||
dropInventory(playerEntity, result);
|
dropInventory(playerEntity, result);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void createGrid(List<Pair<Integer, Integer>> grid, List<Pair<Integer, Integer>> gemPos) {
|
/**
|
||||||
|
* Creates a hexagonal crafting grid.
|
||||||
|
* @param grid Output for normal slot positions.
|
||||||
|
* @param gemPos Output for the gem slot position.
|
||||||
|
*/
|
||||||
|
private static void createGrid(List<int[]> grid, List<int[]> gemPos) {
|
||||||
int cols = 4;
|
int cols = 4;
|
||||||
int spacing = 23;
|
int spacing = 23;
|
||||||
|
|
||||||
|
@ -203,7 +217,25 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
|
|
||||||
for (int row = 0; row < 7; row++) {
|
for (int row = 0; row < 7; row++) {
|
||||||
for (int i = 0; i < cols; i++) {
|
for (int i = 0; i < cols; i++) {
|
||||||
(row == 3 && i == 3 ? gemPos : grid).add(new Pair<>(left + (i * spacing), top));
|
|
||||||
|
int ring = 3;
|
||||||
|
if (row == 0 || row == 6) {
|
||||||
|
ring = 1;
|
||||||
|
} else if ((row == 1 || row == 5) && i > 0 && i < cols - 1) {
|
||||||
|
ring = 2;
|
||||||
|
} else {
|
||||||
|
if (i == 0 || i == cols - 1) {
|
||||||
|
ring = 1;
|
||||||
|
} else if (i == 1 || i == cols - 2) {
|
||||||
|
ring = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(row == 3 && i == 3 ? gemPos : grid).add(new int[] {
|
||||||
|
left + (i * spacing),
|
||||||
|
top,
|
||||||
|
row == 3 && i == 3 ? 4 : ring
|
||||||
|
});
|
||||||
}
|
}
|
||||||
top += spacing * 0.9;
|
top += spacing * 0.9;
|
||||||
left -= (spacing / 2) * (row > 2 ? -1 : 1);
|
left -= (spacing / 2) * (row > 2 ? -1 : 1);
|
||||||
|
@ -211,7 +243,9 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface SpellbookSlot {}
|
public interface SpellbookSlot {
|
||||||
|
int getRing();
|
||||||
|
}
|
||||||
|
|
||||||
public class SpellbookInventory extends CraftingInventory {
|
public class SpellbookInventory extends CraftingInventory {
|
||||||
|
|
||||||
|
@ -220,38 +254,74 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack getItemToModify() {
|
public ItemStack getItemToModify() {
|
||||||
return gemSlot.getStack();
|
return gemSlot.uncrafted.orElse(gemSlot.getStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRing(int slot) {
|
||||||
|
Slot s = slots.get(slot);
|
||||||
|
return s instanceof SpellbookSlot ? ((SpellbookSlot)s).getRing() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpellTraits getTraits() {
|
||||||
|
return SpellTraits.union(InventoryUtil.slots(this)
|
||||||
|
.map(slot -> SpellTraits.of(getStack(slot)).multiply(getRingFactor(getRing(slot))))
|
||||||
|
.toArray(SpellTraits[]::new)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float getRingFactor(int ring) {
|
||||||
|
switch (ring) {
|
||||||
|
case 1: return 1;
|
||||||
|
case 2: return 0.6F;
|
||||||
|
case 3: return 0.3F;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InputSlot extends Slot implements SpellbookSlot {
|
public class InputSlot extends Slot implements SpellbookSlot {
|
||||||
public InputSlot(Inventory inventory, int index, int xPosition, int yPosition) {
|
private final int ring;
|
||||||
super(inventory, index, xPosition, yPosition);
|
|
||||||
|
public InputSlot(Inventory inventory, int index, int[] params) {
|
||||||
|
super(inventory, index, params[0], params[1]);
|
||||||
|
ring = params[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxItemCount() {
|
public int getMaxItemCount() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRing() {
|
||||||
|
return ring;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class OutputSlot extends CraftingResultSlot implements SpellbookSlot {
|
public static class OutputSlot extends CraftingResultSlot implements SpellbookSlot {
|
||||||
|
|
||||||
private Optional<ItemStack> uncrafted = Optional.empty();
|
private Optional<ItemStack> uncrafted = Optional.empty();
|
||||||
|
|
||||||
|
private final PlayerEntity player;
|
||||||
private final SpellbookInventory input;
|
private final SpellbookInventory input;
|
||||||
|
|
||||||
public OutputSlot(PlayerEntity player, SpellbookInventory input, Inventory inventory, int index, int x, int y) {
|
private final int ring;
|
||||||
super(player, input, inventory, index, x, y);
|
|
||||||
|
public OutputSlot(PlayerEntity player, SpellbookInventory input, Inventory inventory, int index, int[] params) {
|
||||||
|
super(player, input, inventory, index, params[0], params[1]);
|
||||||
|
this.player = player;
|
||||||
this.input = input;
|
this.input = input;
|
||||||
|
this.ring = params[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCrafted(ItemStack crafted) {
|
public void setCrafted(ItemStack crafted) {
|
||||||
uncrafted = uncrafted.or(() -> Optional.of(getStack()));
|
uncrafted = uncrafted.or(() -> Optional.of(getStack()));
|
||||||
setStack(crafted);
|
setStack(crafted);
|
||||||
|
player.playSound(SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.MASTER, 1, 0.3F);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUncrafted() {
|
public void setUncrafted() {
|
||||||
|
player.playSound(SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, SoundCategory.MASTER, 0.2F, 0.2F);
|
||||||
uncrafted = uncrafted.filter(stack -> {
|
uncrafted = uncrafted.filter(stack -> {
|
||||||
setStack(stack);
|
setStack(stack);
|
||||||
return false;
|
return false;
|
||||||
|
@ -268,6 +338,11 @@ public class SpellbookScreenHandler extends ScreenHandler {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRing() {
|
||||||
|
return ring;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTakeItem(PlayerEntity player, ItemStack stack) {
|
public void onTakeItem(PlayerEntity player, ItemStack stack) {
|
||||||
if (uncrafted.isPresent()) {
|
if (uncrafted.isPresent()) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.minelittlepony.unicopia.entity;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
import com.minelittlepony.unicopia.container.SpellbookScreenHandler;
|
||||||
import com.minelittlepony.unicopia.item.UItems;
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.util.TriState;
|
import net.fabricmc.fabric.api.util.TriState;
|
||||||
|
@ -18,6 +18,7 @@ import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext;
|
||||||
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
|
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
|
||||||
import net.minecraft.sound.BlockSoundGroup;
|
import net.minecraft.sound.BlockSoundGroup;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
@ -197,7 +198,7 @@ public class SpellbookEntity extends MobEntity {
|
||||||
|
|
||||||
if (isOpen() && EquinePredicates.PLAYER_UNICORN.test(player)) {
|
if (isOpen() && EquinePredicates.PLAYER_UNICORN.test(player)) {
|
||||||
setBored(false);
|
setBored(false);
|
||||||
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((syncId, inv, ply) -> UScreenHandlers.SPELL_BOOK.create(syncId, inv), getDisplayName()));
|
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((syncId, inv, ply) -> new SpellbookScreenHandler(syncId, inv, ScreenHandlerContext.create(world, getBlockPos())), getDisplayName()));
|
||||||
player.playSound(SoundEvents.ITEM_BOOK_PAGE_TURN, 2, 1);
|
player.playSound(SoundEvents.ITEM_BOOK_PAGE_TURN, 2, 1);
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.minelittlepony.unicopia.util;
|
package com.minelittlepony.unicopia.util;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.google.common.collect.AbstractIterator;
|
import com.google.common.collect.AbstractIterator;
|
||||||
|
|
||||||
import net.minecraft.inventory.Inventory;
|
import net.minecraft.inventory.Inventory;
|
||||||
|
@ -19,4 +21,8 @@ public interface InventoryUtil {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Stream<Integer> slots(Inventory inventory) {
|
||||||
|
return Stream.iterate(0, i -> i < inventory.size(), i -> i + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue