Rewrote the spellbook pages system

This commit is contained in:
Sollace 2019-02-08 17:56:28 +02:00
parent fc26e84fa2
commit 8c3ad677b9
27 changed files with 706 additions and 360 deletions

View file

@ -47,6 +47,7 @@ import com.minelittlepony.jumpingcastle.api.JumpingCastle;
import com.minelittlepony.unicopia.advancements.UAdvancements;
import com.minelittlepony.unicopia.block.ITillable;
import com.minelittlepony.unicopia.command.Commands;
import com.minelittlepony.unicopia.enchanting.Pages;
import com.minelittlepony.unicopia.enchanting.SpellRecipe;
import com.minelittlepony.unicopia.forgebullshit.FBS;
import com.minelittlepony.unicopia.inventory.gui.ContainerSpellBook;
@ -112,6 +113,8 @@ public class Unicopia implements IGuiHandler {
}
};
Pages.instance().load();
Biome.REGISTRY.forEach(UEntities::registerSpawnEntries);
UClient.instance().posInit(event);

View file

@ -1,32 +0,0 @@
package com.minelittlepony.unicopia.enchanting;
import com.minelittlepony.unicopia.UItems;
import com.minelittlepony.unicopia.enchanting.PagesList.IPageEvent;
import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.item.ItemStack;
/**
* A basic event for unlocking a page when a gem is crafted for the given spell
*/
public class BasicCraftingEvent implements IPageEvent {
private final String matched;
private final int pageIndex;
public BasicCraftingEvent(int page, String effectName) {
matched = effectName;
pageIndex = page;
}
@Override
public boolean matches(IPageOwner prop, ItemStack stack) {
return stack.getItem() == UItems.spell && SpellRegistry.getKeyFromStack(stack).equals(matched);
}
@Override
public int getPage(int stackSize) {
return pageIndex;
}
}

View file

@ -0,0 +1,56 @@
package com.minelittlepony.unicopia.enchanting;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class CompoundCondition implements IUnlockCondition<IUnlockEvent> {
final Op operation;
final List<IUnlockCondition<IUnlockEvent>> conditions = Lists.newArrayList();
CompoundCondition(JsonObject json) {
require(json, "operation");
require(json, "conditions");
operation = Op.valueOf(json.get("operation").getAsString().toUpperCase());
json.get("conditions").getAsJsonArray().forEach(this::addElement);
}
void addElement(JsonElement element) {
JsonObject obj = element.getAsJsonObject();
conditions.add(Pages.instance().createCondition(obj));
}
@Override
public boolean accepts(IUnlockEvent event) {
return true;
}
@Override
public boolean matches(IPageOwner owner, IUnlockEvent event) {
return operation.test.apply(conditions.stream(), condition -> condition.accepts(event) && condition.matches(owner, event));
}
enum Op {
AND(Stream::allMatch),
OR(Stream::anyMatch);
final Test test;
Op(Test test) {
this.test = test;
}
interface Test {
boolean apply(Stream<IUnlockCondition<IUnlockEvent>> stream, Predicate<IUnlockCondition<IUnlockEvent>> predicate);
}
}
}

View file

@ -0,0 +1,8 @@
package com.minelittlepony.unicopia.enchanting;
import com.google.gson.JsonObject;
@FunctionalInterface
public interface IConditionFactory {
IUnlockCondition<?> create(JsonObject json);
}

View file

@ -0,0 +1,40 @@
package com.minelittlepony.unicopia.enchanting;
import net.minecraft.util.ResourceLocation;
/**
* A spellbook page
*/
public interface IPage extends Comparable<IPage> {
/**
* Gets the index.
* This is the position the page appears in the book gui.
*/
int getIndex();
/**
* The unique name of this page.
*/
ResourceLocation getName();
/**
* Tests unlock conditions for this page.
* Returns true if the owner is permitted to read this page.
*/
boolean canUnlock(IPageOwner owner, IUnlockEvent event);
/**
* Gets the texture.
* This is what's shown when this page is opened in the book gui.
*/
ResourceLocation getTexture();
/**
* The default state.
*/
PageState getDefaultState();
IPage next();
IPage prev();
}

View file

@ -1,32 +1,32 @@
package com.minelittlepony.unicopia.enchanting;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import com.minelittlepony.unicopia.network.ITransmittable;
import net.minecraft.util.ResourceLocation;
/**
* Interface for things that own and can unlock pages.
*
*/
public interface IPageOwner extends ITransmittable {
@Nonnull
List<Integer> getUnlockedPages();
Map<ResourceLocation, PageState> getPageStates();
default boolean hasPageUnlock(int pageIndex) {
return getUnlockedPages().contains(pageIndex);
}
default boolean unlockPage(int pageIndex) {
if (!hasPageUnlock(pageIndex)) {
if (getUnlockedPages().add(pageIndex)) {
sendCapabilities(true);
return true;
}
default void setPageState(IPage page, PageState state) {
if (state == PageState.LOCKED) {
getPageStates().remove(page.getName());
} else {
getPageStates().put(page.getName(), state);
}
return false;
sendCapabilities(true);
}
default boolean hasUnlockedPages() {
return getUnlockedPages().size() > 0;
default PageState getPageState(IPage page) {
return getPageStates().getOrDefault(page.getName(), page.getDefaultState());
}
}

View file

@ -1,5 +1,12 @@
package com.minelittlepony.unicopia.enchanting;
@FunctionalInterface
public interface IPageUnlockListener {
public void onPageUnlocked();
/**
* Called when a page is unlocked.
*
* @param page The page that has been unlocked
* @return True to allow, false to block.
*/
boolean onPageUnlocked(IPage page);
}

View file

@ -0,0 +1,30 @@
package com.minelittlepony.unicopia.enchanting;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
/**
* A PageEvent for determining when certain pages must be unlocked.
*/
public interface IUnlockCondition<T extends IUnlockEvent> {
/**
* Returns true if event instanceof T
*/
default boolean accepts(IUnlockEvent event) {
return true;
}
/**
* Checks if this event's conditions are met.
* @param prop PlayerExtension for the player doing the crafting
* @param stack ItemStack crafted
*/
boolean matches(IPageOwner owner, T event);
default void require(JsonObject json, String memberName) {
if (!json.has(memberName)) {
throw new JsonParseException(String.format("%s condition must have a %s", getClass().getSimpleName(), memberName));
}
}
}

View file

@ -0,0 +1,5 @@
package com.minelittlepony.unicopia.enchanting;
public interface IUnlockEvent {
}

View file

@ -1,41 +0,0 @@
package com.minelittlepony.unicopia.enchanting;
import com.minelittlepony.unicopia.enchanting.PagesList.IPageEvent;
import net.minecraft.item.ItemStack;
/**
* An unlock event that requires other pages to be unlocked before it too can be unlocked.
*
*/
public class MultiPageUnlockEvent implements IPageEvent {
private final int pageIndex;
private final int[][] otherPageIndeces;
public MultiPageUnlockEvent(int page, int[]... otherPages) {
pageIndex = page;
otherPageIndeces = otherPages;
}
@Override
public boolean matches(IPageOwner prop, ItemStack stack) {
for (int i = 0; i < otherPageIndeces.length; i++) {
if (!checkPageUnlockSet(prop, otherPageIndeces[i])) return false;
}
return true;
}
private boolean checkPageUnlockSet(IPageOwner prop, int[] pages) {
for (int i = 0; i < pages.length; i++) {
if (prop.hasPageUnlock(pages[i])) return true;
}
return false;
}
@Override
public int getPage(int stackSize) {
return pageIndex;
}
}

View file

@ -0,0 +1,100 @@
package com.minelittlepony.unicopia.enchanting;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
import net.minecraft.util.ResourceLocation;
class PageInstance implements IPage {
int index;
@Nonnull
ResourceLocation name;
@Nonnull
ResourceLocation texture;
@Nullable
IUnlockCondition<IUnlockEvent> condition;
@Expose
PageState state = PageState.LOCKED;
PageInstance(ResourceLocation id, JsonObject json) {
this.name = id;
if (json.has("state")) {
state = PageState.of(json.get("state").getAsString());
}
if (json.has("condition")) {
condition = Pages.instance().createCondition(json.get("condition").getAsJsonObject());
}
String full = json.get("texture").getAsString();
String[] loc = full.split(":");
if (loc.length < 2) {
loc = new String[] { "minecraft", full };
}
if ("minecraft".equals(loc[0]) && !"minecraft".equals(id.getNamespace())) {
loc[0] = id.getNamespace();
}
texture = new ResourceLocation(loc[0], String.format("textures/pages/%s.png", loc[1]));
}
@Override
public int getIndex() {
return index;
}
@Override
public ResourceLocation getName() {
return name;
}
@Override
public ResourceLocation getTexture() {
return texture;
}
@Override
public PageState getDefaultState() {
return state;
}
@Override
public boolean canUnlock(IPageOwner owner, IUnlockEvent event) {
return condition == null || condition.accepts(event) && condition.matches(owner, event);
}
@Override
public IPage next() {
int i = Math.min(Pages.instance().getTotalPages() - 1, index + 1);
return Pages.instance().getByIndex(i);
}
@Override
public IPage prev() {
if (index <= 0) {
return this;
}
return Pages.instance().getByIndex(index - 1);
}
@Override
public int compareTo(IPage o) {
return getIndex() - o.getIndex();
}
@Override
public boolean equals(Object o) {
return o instanceof IPage && getName().equals(((IPage)o).getName());
}
}

View file

@ -0,0 +1,24 @@
package com.minelittlepony.unicopia.enchanting;
public enum PageState {
LOCKED,
UNREAD,
READ;
public boolean isLocked() {
return this == LOCKED;
}
public boolean isUnread() {
return this == UNREAD;
}
public static PageState of(String s) {
try {
if (s != null)
return valueOf(s.toUpperCase());
} catch (Throwable e) {}
return PageState.LOCKED;
}
}

View file

@ -0,0 +1,31 @@
package com.minelittlepony.unicopia.enchanting;
import com.google.gson.JsonObject;
import net.minecraft.util.ResourceLocation;
public class PageStateCondition implements IUnlockCondition<IUnlockEvent> {
ResourceLocation page;
PageState state;
PageStateCondition(JsonObject json) {
require(json, "page");
require(json, "state");
page = new ResourceLocation(json.get("page").getAsString());
state = PageState.of(json.get("state").getAsString());
}
@Override
public boolean matches(IPageOwner owner, IUnlockEvent event) {
IPage ipage = Pages.instance().getByName(page);
if (ipage != null) {
return owner.getPageState(ipage) == state;
}
return false;
}
}

View file

@ -0,0 +1,97 @@
package com.minelittlepony.unicopia.enchanting;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.minelittlepony.util.AssetWalker;
import net.minecraft.util.ResourceLocation;
public class Pages {
private static final Pages instance = new Pages();
public static Pages instance() {
return instance;
}
private final Map<ResourceLocation, IPage> pages = Maps.newHashMap();
private final List<IPage> pagesByIndex = Lists.newArrayList();
private final Map<String, IConditionFactory> conditionFactories = Maps.newHashMap();
private final AssetWalker assets = new AssetWalker(new ResourceLocation("unicopia", "pages"), this::addPage);
Pages() {
registerConditionFactory("unicopia:compound_condition", CompoundCondition::new);
registerConditionFactory("unicopia:page_state", PageStateCondition::new);
registerConditionFactory("unicopia:spell_crafting", SpellCraftingEvent.Condition::new);
}
public void load() {
pages.clear();
pagesByIndex.clear();
assets.walk();
int index = 0;
for (IPage ipage : pages.values()) {
((PageInstance)ipage).index = index++;
pagesByIndex.add(ipage);
}
}
void addPage(ResourceLocation id, JsonObject json) throws JsonParseException {
pages.put(id, new PageInstance(id, json));
}
@SuppressWarnings("unchecked")
<T extends IUnlockEvent> IUnlockCondition<T> createCondition(JsonObject json) {
String key = json.get("key").getAsString();
return (IUnlockCondition<T>)conditionFactories.get(key).create(json);
}
@Nullable
public IPage getByName(ResourceLocation name) {
return pages.get(name);
}
@Nullable
public IPage getByIndex(int index) {
return pagesByIndex.get(index);
}
public Stream<IPage> getUnlockablePages(Predicate<IPage> predicate) {
return pages.values().stream().filter(predicate);
}
public void triggerUnlockEvent(IPageOwner owner, IUnlockEvent event, @Nullable IPageUnlockListener unlockListener) {
pages.values().stream()
.filter(page -> page.canUnlock(owner, event))
.forEach(page -> unlockPage(owner, page, unlockListener));
}
public void unlockPage(IPageOwner owner, IPage page, @Nullable IPageUnlockListener unlockListener) {
if (owner.getPageState(page).isLocked()) {
if (unlockListener == null || unlockListener.onPageUnlocked(page)) {
owner.setPageState(page, PageState.UNREAD);
}
}
}
public void registerConditionFactory(String conditionType, IConditionFactory factory) {
conditionFactories.put(conditionType, factory);
}
public int getTotalPages() {
return pages.size();
}
}

View file

@ -1,117 +0,0 @@
package com.minelittlepony.unicopia.enchanting;
import java.util.ArrayList;
import java.util.List;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
public class PagesList {
private static final List<Integer> unreadPages = new ArrayList<Integer>();
private static final List<IPageEvent> pageEvents = new ArrayList<IPageEvent>();
private static int totalPages = 0;
/**
* Sets the maximum number of pages displayed in the spellbook.
* Only allows widening. Total pages cannot be reduced.
*/
public static void setTotalPages(int pages) {
if (pages > totalPages) {
totalPages = pages;
}
}
public static int getTotalPages() {
return totalPages;
}
/**
* Registers an event for unlocking a page.
*/
public static void registerPageEvent(IPageEvent event) {
pageEvents.add(event);
}
/**
* Marks a page as read
*/
public static void readPage(int pageIndex) {
unreadPages.remove(Integer.valueOf(pageIndex));
}
/**
* Checks if there are any pages after the given index that are unread
* Only useful on the client
*/
public static boolean hasUnreadPagesAfter(int pageIndex) {
for (Integer i : unreadPages) {
if (i > pageIndex) return true;
}
return false;
}
/**
* Checks if there are any pages before the given index that are unread
* Only useful on the client
*/
public static boolean hasUnreadPagesBefore(int pageIndex) {
for (Integer i : unreadPages) {
if (i < pageIndex) return true;
}
return false;
}
/**
* Checks if the given page has been read yet.
* Only of use on the client
*/
public static boolean isPageUnread(int pageIndex) {
return unreadPages.contains(pageIndex);
}
private static boolean unlockPages(IPageOwner prop, ItemStack stack) {
boolean result = false;
if (stack != null && stack.getCount() > 0) {
for (IPageEvent i : pageEvents) {
if (i.matches(prop, stack)) {
int page = i.getPage(stack.getCount());
if (page >= 0 && prop.unlockPage(page)) {
result |= unreadPages.add(page);
}
}
}
}
return result;
}
/**
* Checks for, and unlocks any pages that can be unlocked by the given item for the given player
* @return True if a page was unlocked, false otherwise
*/
public static boolean unlockPage(EntityPlayer player, ItemStack stack) {
return unlockPages(PlayerSpeciesList.instance().getPlayer(player), stack);
}
/**
* A PageEvent for determining when certain pages must be unlocked.
*
*/
public static interface IPageEvent {
/**
* Checks if this event's conditions are met.
* @param prop PlayerExtension for the player doing the crafting
* @param stack ItemStack crafted
*/
public boolean matches(IPageOwner prop, ItemStack stack);
/**
* Gets the page number corresponding to the given stack for this event
*/
public int getPage(int stackSize);
}
}

View file

@ -0,0 +1,61 @@
package com.minelittlepony.unicopia.enchanting;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
import com.minelittlepony.unicopia.item.ItemSpell;
import com.minelittlepony.unicopia.spell.SpellAffinity;
import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.item.ItemStack;
/**
* A basic event for unlocking a page when a gem is crafted for the given spell
*/
public class SpellCraftingEvent {
public static void trigger(IPageOwner owner, ItemStack stack, @Nullable IPageUnlockListener unlockListener) {
Pages.instance().triggerUnlockEvent(owner, new Event(stack), unlockListener);
}
static class Event implements IUnlockEvent {
final ItemStack stack;
Event(ItemStack stack) {
this.stack = stack;
}
}
static class Condition implements IUnlockCondition<Event> {
@Nonnull
SpellAffinity affinity;
@Expose
String spell;
Condition(JsonObject json) {
require(json, "affinity");
require(json, "spell");
affinity = SpellAffinity.of(json.get("affinity").getAsString());
spell = json.get("spell").getAsString();
}
@Override
public boolean accepts(IUnlockEvent event) {
return event instanceof Event;
}
@Override
public boolean matches(IPageOwner prop, Event event) {
if (!event.stack.isEmpty() && event.stack.getItem() instanceof ItemSpell) {
return ((ItemSpell)event.stack.getItem()).getAffinity() == affinity
&& SpellRegistry.getKeyFromStack(event.stack).equals(spell);
}
return false;
}
}
}

View file

@ -114,7 +114,7 @@ public class EntitySpellbook extends EntityLiving implements IMagicals {
SoundType sound = SoundType.WOOD;
world.playSound(posX, posY, posZ, sound.getBreakSound(), SoundCategory.BLOCKS, sound.getVolume(), sound.getPitch(), true);
if (world.getGameRules().getBoolean("doTileDrops")) {
entityDropItem(new ItemStack(UItems.spellbook, 1), 0);
entityDropItem(new ItemStack(UItems.spellbook), 0);
}
}
return false;

View file

@ -9,6 +9,7 @@ import com.minelittlepony.unicopia.inventory.InventorySpellBook;
import com.minelittlepony.unicopia.inventory.slot.SlotEnchanting;
import com.minelittlepony.unicopia.inventory.slot.SlotEnchantingResult;
import com.minelittlepony.unicopia.item.ItemSpell;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.entity.player.EntityPlayer;
@ -64,7 +65,7 @@ public class ContainerSpellBook extends Container {
addSlotToContainer(new SlotEnchanting(craftMatrix, 2, 180, 134));
addSlotToContainer(new SlotEnchanting(craftMatrix, 3, 231, 120));
addSlotToContainer(new SlotEnchanting(craftMatrix, 4, 232, 65));
addSlotToContainer(resultSlot = new SlotEnchantingResult(listener, player, craftMatrix, craftResult, 0, 196, 92));
addSlotToContainer(resultSlot = new SlotEnchantingResult(listener, PlayerSpeciesList.instance().getPlayer(player), craftMatrix, craftResult, 0, 196, 92));
}
@Override

View file

@ -4,8 +4,11 @@ import java.io.IOException;
import org.lwjgl.opengl.GL11;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.enchanting.IPage;
import com.minelittlepony.unicopia.enchanting.IPageUnlockListener;
import com.minelittlepony.unicopia.enchanting.PagesList;
import com.minelittlepony.unicopia.enchanting.PageState;
import com.minelittlepony.unicopia.enchanting.Pages;
import com.minelittlepony.unicopia.inventory.slot.SlotEnchanting;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
@ -21,20 +24,21 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.ResourceLocation;
public class GuiSpellBook extends GuiContainer implements IPageUnlockListener {
private static int currentPage = 0;
private static ResourceLocation spellBookPageTextures = new ResourceLocation("unicopia", "textures/gui/container/pages/page-" + currentPage + ".png");
private static IPage currentIPage;
private static final ResourceLocation spellBookGuiTextures = new ResourceLocation("unicopia", "textures/gui/container/book.png");
private IPlayer playerExtension;
private PageButton nextPage;
private PageButton prevPage;
public GuiSpellBook(EntityPlayer player) {
super(new ContainerSpellBook(player.inventory, player.world, new BlockPos(player)));
player.openContainer = inventorySlots;
((ContainerSpellBook)inventorySlots).setListener(this);
xSize = 405;
ySize = 219;
allowUserInput = true;
@ -51,6 +55,12 @@ public class GuiSpellBook extends GuiContainer implements IPageUnlockListener {
buttonList.add(nextPage = new PageButton(1, x + 360, y + 160, true));
buttonList.add(prevPage = new PageButton(2, x + 20, y + 160, false));
if (currentIPage == null) {
currentIPage = Pages.instance().getByIndex(0);
}
onPageChange();
}
@Override
@ -58,45 +68,37 @@ public class GuiSpellBook extends GuiContainer implements IPageUnlockListener {
initGui();
if (button.id == 1) {
nextPage();
currentIPage = currentIPage.next();
} else {
prevPage();
currentIPage = currentIPage.prev();
}
onPageChange();
}
public void nextPage() {
if (currentPage == 0) {
playerExtension.unlockPage(1);
}
if (currentPage < PagesList.getTotalPages() - 1) {
currentPage++;
spellBookPageTextures = new ResourceLocation("unicopia", "textures/gui/container/pages/page-" + currentPage + ".png");
protected void onPageChange() {
prevPage.visible = currentIPage.getIndex() > 0;
nextPage.visible = currentIPage.getIndex() < Pages.instance().getTotalPages() - 1;
onPageUnlocked();
PagesList.readPage(currentPage);
}
}
@Override
public void onPageUnlocked() {
if (PagesList.hasUnreadPagesAfter(currentPage)) {
nextPage.triggerShake();
}
if (PagesList.hasUnreadPagesBefore(currentPage)) {
prevPage.triggerShake();
if (playerExtension.getPageState(currentIPage) == PageState.UNREAD) {
playerExtension.setPageState(currentIPage, PageState.READ);
}
}
public void prevPage() {
if (currentPage > 0) {
currentPage--;
spellBookPageTextures = new ResourceLocation("unicopia", "textures/gui/container/pages/page-" + currentPage + ".png");
@Override
public boolean onPageUnlocked(IPage page) {
int i = currentIPage.compareTo(page);
onPageUnlocked();
PagesList.readPage(currentPage);
}
}
if (i <= 0) {
prevPage.triggerShake();
}
if (i >= 0) {
nextPage.triggerShake();
}
return true;
}
@Override
protected void drawGradientRect(int left, int top, int width, int height, int startColor, int endColor) {
@ -128,10 +130,9 @@ public class GuiSpellBook extends GuiContainer implements IPageUnlockListener {
@Override
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
if (PagesList.getTotalPages() > 0) {
String text = (currentPage + 1) + "/" + PagesList.getTotalPages();
fontRenderer.drawString(text, 203 - fontRenderer.getStringWidth(text)/2, 165, 0x0);
}
String text = String.format("%d / %d", currentIPage.getIndex() + 1, Pages.instance().getTotalPages());
fontRenderer.drawString(text, 203 - fontRenderer.getStringWidth(text)/2, 165, 0x0);
}
@Override
@ -147,12 +148,18 @@ public class GuiSpellBook extends GuiContainer implements IPageUnlockListener {
GlStateManager.enableBlend();
GL11.glDisable(GL11.GL_ALPHA_TEST);
if (playerExtension.hasPageUnlock(currentPage)) {
if (mc.getTextureManager().getTexture(spellBookPageTextures) != TextureUtil.MISSING_TEXTURE) {
if (playerExtension.getPageState(currentIPage) != PageState.LOCKED) {
ResourceLocation texture = currentIPage.getTexture();
if (mc.getTextureManager().getTexture(texture) != TextureUtil.MISSING_TEXTURE) {
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
mc.getTextureManager().bindTexture(spellBookPageTextures);
mc.getTextureManager().bindTexture(texture);
drawModalRectWithCustomSizedTexture(left, top, 0, 0, xSize, ySize, 512, 256);
} else {
if (playerExtension.getWorld().rand.nextInt(100) == 0) {
Unicopia.log.fatal("Missing texture " + texture);
}
}
}

View file

@ -1,8 +1,9 @@
package com.minelittlepony.unicopia.inventory.slot;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.enchanting.IPageOwner;
import com.minelittlepony.unicopia.enchanting.IPageUnlockListener;
import com.minelittlepony.unicopia.enchanting.PagesList;
import com.minelittlepony.unicopia.enchanting.SpellCraftingEvent;
import com.minelittlepony.unicopia.inventory.InventorySpellBook;
import com.minelittlepony.unicopia.item.ItemSpell;
import com.minelittlepony.unicopia.spell.SpellRegistry;
@ -14,14 +15,14 @@ import net.minecraft.util.NonNullList;
public class SlotEnchantingResult extends SlotEnchanting {
private final EntityPlayer thePlayer;
private final IPageOwner owner;
private final InventorySpellBook craftMatrix;
private IPageUnlockListener listener;
public SlotEnchantingResult(IPageUnlockListener listener, EntityPlayer player, InventorySpellBook craftMatric, IInventory inventory, int index, int xPosition, int yPosition) {
public SlotEnchantingResult(IPageUnlockListener listener, IPageOwner owner, InventorySpellBook craftMatric, IInventory inventory, int index, int xPosition, int yPosition) {
super(inventory, index, xPosition, yPosition);
thePlayer = player;
this.owner = owner;
this.listener = listener;
craftMatrix = craftMatric;
}
@ -75,13 +76,7 @@ public class SlotEnchantingResult extends SlotEnchanting {
@Override
protected void onCrafting(ItemStack stack) {
if (PagesList.unlockPage(thePlayer, stack) && listener != null) {
listener.onPageUnlocked();
}
if (listener != null) {
listener.onPageUnlocked();
}
SpellCraftingEvent.trigger(owner, stack, listener);
}
@Override

View file

@ -56,7 +56,6 @@ public class ItemSpellbook extends ItemBook {
BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(this, dispenserBehavior);
}
public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) {
if (!world.isRemote && Predicates.MAGI.test(player)) {

View file

@ -1,16 +1,16 @@
package com.minelittlepony.unicopia.player;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.minelittlepony.model.anim.BasicEasingInterpolator;
import com.minelittlepony.model.anim.IInterpolator;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.UEffects;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.enchanting.PageState;
import com.minelittlepony.unicopia.network.EffectSync;
import com.minelittlepony.unicopia.network.MsgPlayerCapabilities;
import com.minelittlepony.unicopia.spell.IMagicEffect;
@ -24,13 +24,13 @@ import net.minecraft.init.MobEffects;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagIntArray;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.network.play.server.SPacketSetPassengers;
import net.minecraft.potion.PotionEffect;
import net.minecraft.stats.StatList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.EnumDifficulty;
class PlayerCapabilities implements IPlayer {
@ -47,7 +47,7 @@ class PlayerCapabilities implements IPlayer {
private static final DataParameter<NBTTagCompound> EFFECT = EntityDataManager
.createKey(EntityPlayer.class, DataSerializers.COMPOUND_TAG);
private final List<Integer> pages = Lists.newArrayList();
private final Map<ResourceLocation, PageState> pageStates = Maps.newHashMap();
private final PlayerAbilityDelegate powers = new PlayerAbilityDelegate(this);
@ -289,15 +289,27 @@ class PlayerCapabilities implements IPlayer {
compound.setTag("powers", powers.toNBT());
compound.setTag("gravity", gravity.toNBT());
if (hasUnlockedPages()) {
compound.setTag("pages", new NBTTagIntArray(pages));
}
IMagicEffect effect = getEffect();
if (effect != null) {
compound.setTag("effect", SpellRegistry.instance().serializeEffectToNBT(effect));
}
if (!pageStates.isEmpty()) {
NBTTagCompound pages = new NBTTagCompound();
boolean written = false;
for (Map.Entry<ResourceLocation, PageState> entry : pageStates.entrySet()) {
if (entry.getValue() != PageState.LOCKED) {
pages.setString(entry.getKey().toString(), entry.getValue().name());
written = true;
}
}
if (written) {
compound.setTag("pageStates", pages);
}
}
}
@Override
@ -311,17 +323,22 @@ class PlayerCapabilities implements IPlayer {
setEffect(SpellRegistry.instance().createEffectFromNBT(compound.getCompoundTag("effect")));
}
if (compound.hasKey("pages")) {
pages.clear();
for (int i : compound.getIntArray("pages")) {
pages.add(i);
pageStates.clear();
if (compound.hasKey("pageStates")) {
NBTTagCompound pages = compound.getCompoundTag("pageStates");
for (String key : pages.getKeySet()) {
PageState state = PageState.of(pages.getString(key));
if (state != PageState.LOCKED) {
pageStates.put(new ResourceLocation(key), state);
}
}
}
}
@Override
public void copyFrom(IPlayer oldPlayer) {
pages.addAll(oldPlayer.getUnlockedPages());
setEffect(oldPlayer.getEffect());
setPlayerSpecies(oldPlayer.getPlayerSpecies());
}
@ -363,8 +380,8 @@ class PlayerCapabilities implements IPlayer {
public void setCurrentLevel(int level) {
}
@Nonnull
public List<Integer> getUnlockedPages() {
return pages;
@Override
public Map<ResourceLocation, PageState> getPageStates() {
return pageStates;
}
}

View file

@ -47,4 +47,13 @@ public enum SpellAffinity {
return implications;
}
public static SpellAffinity of(String s) {
try {
if (s != null)
return valueOf(s.toUpperCase());
} catch (Throwable e) {}
return SpellAffinity.NEUTRAL;
}
}

View file

@ -1,33 +1,16 @@
package com.minelittlepony.unicopia.util.crafting;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import com.minelittlepony.util.AssetWalker;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
@ -41,30 +24,30 @@ import net.minecraft.world.World;
public class CraftingManager {
private static final Logger LOGGER = LogManager.getLogger();
private final Map<ResourceLocation, IRecipe> REGISTRY = Maps.newHashMap();
private final Map<String, Function<JsonObject, IRecipe>> JSON_PARSERS = Maps.newHashMap();
private static final Gson gson = new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.create();
@Nonnull
private final ResourceLocation crafting_id;
private final AssetWalker assets;
public CraftingManager(String modid, String resourcename) {
this(new ResourceLocation(modid, resourcename + "/recipes"));
}
public CraftingManager(@Nonnull ResourceLocation id) {
crafting_id = id;
assets = new AssetWalker(id, this::handleJson);
load();
}
protected void handleJson(ResourceLocation id, JsonObject json) throws JsonParseException {
REGISTRY.put(id, parseRecipeJson(json));
}
protected void registerRecipeTypes(Map<String, Function<JsonObject, IRecipe>> types) {
types.put("crafting_shaped", ShapedRecipes::deserialize);
types.put("crafting_shapeless", ShapelessRecipes::deserialize);
@ -76,62 +59,7 @@ public class CraftingManager {
registerRecipeTypes(JSON_PARSERS);
try {
String loadLocation = "/assets/" + crafting_id.getNamespace() + "/" + crafting_id.getPath();
URL url = CraftingManager.class.getResource(loadLocation);
if (url == null) {
LOGGER.error("Couldn't find .mcassetsroot");
return;
}
URI uri = url.toURI();
if ("file".equals(uri.getScheme())) {
loadRecipesFrom(Paths.get(CraftingManager.class.getResource(loadLocation).toURI()));
} else {
if (!"jar".equals(uri.getScheme())) {
LOGGER.error("Unsupported scheme " + uri + " trying to list all recipes");
return;
}
try (FileSystem filesystem = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
loadRecipesFrom(filesystem.getPath(loadLocation));
}
}
} catch (IOException | URISyntaxException e) {
LOGGER.error("Couldn't get a list of all recipe files", e);
}
}
private void loadRecipesFrom(@Nullable Path path) throws IOException {
if (path == null) {
return;
}
Iterator<Path> iterator = Files.walk(path).iterator();
while (iterator.hasNext()) {
Path i = iterator.next();
if ("json".equals(FilenameUtils.getExtension(i.toString()))) {
ResourceLocation id = new ResourceLocation(FilenameUtils.removeExtension(path.relativize(i).toString()).replaceAll("\\\\", "/"));
try(BufferedReader bufferedreader = Files.newBufferedReader(i)) {
REGISTRY.put(id, parseRecipeJson(JsonUtils.fromJson(gson, bufferedreader, JsonObject.class)));
} catch (JsonParseException e) {
LOGGER.error("Parsing error loading recipe " + id, e);
return;
} catch (IOException e) {
LOGGER.error("Couldn't read recipe " + id + " from " + i, e);
return;
}
}
}
assets.walk();
}
protected IRecipe parseRecipeJson(JsonObject json) {

View file

@ -0,0 +1,110 @@
package com.minelittlepony.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Iterator;
import javax.annotation.Nullable;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.minelittlepony.unicopia.util.crafting.CraftingManager;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.ResourceLocation;
public class AssetWalker {
private static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.create();
private final String loadLocation;
private final JsonConsumer consumer;
public AssetWalker(ResourceLocation assetLocation, JsonConsumer consumer) {
this.consumer = consumer;
loadLocation = "/assets/" + assetLocation.getNamespace() + "/" + assetLocation.getPath();
}
public void walk() {
try {
URL url = AssetWalker.class.getResource(loadLocation);
if (url == null) {
LOGGER.error("Couldn't find .mcassetsroot");
return;
}
URI uri = url.toURI();
if ("file".equals(uri.getScheme())) {
readFiles(Paths.get(CraftingManager.class.getResource(loadLocation).toURI()));
} else {
if (!"jar".equals(uri.getScheme())) {
LOGGER.error("Unsupported scheme " + uri + " trying to list all recipes");
return;
}
try (FileSystem filesystem = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
readFiles(filesystem.getPath(loadLocation));
}
}
} catch (IOException | URISyntaxException e) {
LOGGER.error("Couldn't get a list of all json files", e);
}
}
private void readFiles(@Nullable Path path) throws IOException {
if (path == null) {
return;
}
Iterator<Path> iterator = Files.walk(path).iterator();
while (iterator.hasNext()) {
Path i = iterator.next();
if ("json".equals(FilenameUtils.getExtension(i.toString()))) {
ResourceLocation id = new ResourceLocation(FilenameUtils.removeExtension(path.relativize(i).toString()).replaceAll("\\\\", "/"));
try(BufferedReader bufferedreader = Files.newBufferedReader(i)) {
consumer.accept(id, JsonUtils.fromJson(GSON, bufferedreader, JsonObject.class));
} catch (JsonParseException e) {
LOGGER.error("Parsing error loading recipe " + id, e);
return;
} catch (IOException e) {
LOGGER.error("Couldn't read recipe " + id + " from " + i, e);
return;
}
}
}
}
@FunctionalInterface
public interface JsonConsumer {
void accept(ResourceLocation id, JsonObject json) throws JsonParseException;
}
}

View file

@ -0,0 +1,8 @@
{
"texture": "unicopia:preface",
"state": "unread",
"conditions": {
"type": "unicopia:compound_condition",
"conditions": []
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB