Add the bag of holding

This commit is contained in:
Sollace 2018-09-19 09:09:30 +02:00
parent bcb0ee9f75
commit 0cb646bb56
19 changed files with 1243 additions and 10 deletions

View file

@ -5,6 +5,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.item.EnumAction; import net.minecraft.item.EnumAction;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.crafting.IRecipe;
import net.minecraftforge.client.event.FOVUpdateEvent; import net.minecraftforge.client.event.FOVUpdateEvent;
import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
@ -29,6 +30,7 @@ import net.minecraftforge.fml.relauncher.SideOnly;
import com.minelittlepony.jumpingcastle.api.IChannel; import com.minelittlepony.jumpingcastle.api.IChannel;
import com.minelittlepony.jumpingcastle.api.JumpingCastle; import com.minelittlepony.jumpingcastle.api.JumpingCastle;
import com.minelittlepony.jumpingcastle.api.Target; import com.minelittlepony.jumpingcastle.api.Target;
import com.minelittlepony.unicopia.advancements.UAdvancements;
import com.minelittlepony.unicopia.client.particle.EntityMagicFX; import com.minelittlepony.unicopia.client.particle.EntityMagicFX;
import com.minelittlepony.unicopia.client.particle.EntityRaindropFX; import com.minelittlepony.unicopia.client.particle.EntityRaindropFX;
import com.minelittlepony.unicopia.client.particle.Particles; import com.minelittlepony.unicopia.client.particle.Particles;
@ -67,19 +69,28 @@ public class Unicopia {
channel.send(new MsgRequestCapabilities(Minecraft.getMinecraft().player), Target.SERVER); channel.send(new MsgRequestCapabilities(Minecraft.getMinecraft().player), Target.SERVER);
}) })
// client ------> server // client ------> server
.consume(MsgRequestCapabilities.class) .consume(MsgRequestCapabilities.class, (msg, channel) -> {
})
// client <------ server // client <------ server
.consume(MsgPlayerCapabilities.class) .consume(MsgPlayerCapabilities.class, (msg, channel) -> {
System.out.println("[CLIENT] Got capabilities for player I am "
+ Minecraft.getMinecraft().player.getGameProfile().getId());
})
// client ------> server // client ------> server
.consume(MsgPlayerAbility.class); .consume(MsgPlayerAbility.class, (msg, channel) -> {
});
MAGIC_PARTICLE = Particles.instance().registerParticle(new EntityMagicFX.Factory()); MAGIC_PARTICLE = Particles.instance().registerParticle(new EntityMagicFX.Factory());
RAIN_PARTICLE = Particles.instance().registerParticle(new EntityRaindropFX.Factory()); RAIN_PARTICLE = Particles.instance().registerParticle(new EntityRaindropFX.Factory());
PowersRegistry.instance().init(); PowersRegistry.instance().init();
UAdvancements.init();
FBS.init(); FBS.init();
} }
@ -93,6 +104,11 @@ public class Unicopia {
UBlocks.registerBlocks(event.getRegistry()); UBlocks.registerBlocks(event.getRegistry());
} }
@SubscribeEvent
public static void registerRecipesStatic(RegistryEvent.Register<IRecipe> event) {
UItems.registerRecipes(event.getRegistry());
}
@SubscribeEvent @SubscribeEvent
public static void registerEntitiesStatic(RegistryEvent.Register<EntityEntry> event) { public static void registerEntitiesStatic(RegistryEvent.Register<EntityEntry> event) {
UEntities.init(event.getRegistry()); UEntities.init(event.getRegistry());

View file

@ -0,0 +1,31 @@
package com.minelittlepony.unicopia.advancements;
import com.google.gson.JsonElement;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.PlayerAdvancements;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.WorldServer;
/**
* Predicate for testing whether a player has a previous advancement.
* Allows for unlocking advancements in linear succession.
*/
public class AdvancementPredicate {
public static AdvancementPredicate deserialize(JsonElement json) {
return new AdvancementPredicate(json.getAsString());
}
private final ResourceLocation id;
public AdvancementPredicate(String advancement) {
this.id = new ResourceLocation(advancement);
}
public boolean test(WorldServer world, PlayerAdvancements playerAdvancements) {
Advancement advancement = world.getAdvancementManager().getAdvancement(id);
return advancement != null && playerAdvancements.getProgress(advancement).isDone();
}
}

View file

@ -0,0 +1,101 @@
package com.minelittlepony.unicopia.advancements;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import net.minecraft.advancements.ICriterionTrigger;
import net.minecraft.advancements.PlayerAdvancements;
import net.minecraft.advancements.critereon.AbstractCriterionInstance;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.WorldServer;
/**
* Advantement trigger for the book of holding. It's an achievement to die so spectacularly! :D
*/
public class BOHDeathTrigger implements ICriterionTrigger<BOHDeathTrigger.Instance> {
private static final ResourceLocation ID = new ResourceLocation("unicopia", "death_by_bag_of_holding");
private final Map<PlayerAdvancements, Entry> listeners = Maps.newHashMap();
@Override
public ResourceLocation getId() {
return ID;
}
@Override
public void addListener(PlayerAdvancements key, Listener<Instance> listener) {
listeners.computeIfAbsent(key, Entry::new).listeners.add(listener);;
}
@Override
public void removeListener(PlayerAdvancements key, Listener<Instance> listener) {
if (listeners.containsKey(key)) {
Entry entry = listeners.get(key);
entry.listeners.remove(listener);
if (entry.listeners.isEmpty()) {
listeners.remove(key);
}
}
}
@Override
public void removeAllListeners(PlayerAdvancements key) {
if (listeners.containsKey(key)) {
listeners.remove(key);
}
}
@Override
public Instance deserializeInstance(JsonObject json, JsonDeserializationContext context) {
return new Instance(AdvancementPredicate.deserialize(json.get("advancement")));
}
public void trigger(EntityPlayerMP player) {
PlayerAdvancements key = player.getAdvancements();
Optional.ofNullable(listeners.get(key)).ifPresent(e -> {
e.trigger((WorldServer)player.world, key);
});
}
static class Instance extends AbstractCriterionInstance {
AdvancementPredicate requirement;
public Instance(AdvancementPredicate requirement) {
super(ID);
this.requirement = requirement;
}
public boolean test(WorldServer world, PlayerAdvancements playerAdvancements) {
return requirement.test(world, playerAdvancements);
}
}
class Entry {
private final PlayerAdvancements advancement;
private final List<Listener<Instance>> listeners = Lists.newArrayList();
Entry(PlayerAdvancements key) {
advancement = key;
}
public void trigger(WorldServer world, PlayerAdvancements playerAdvancements) {
listeners.stream()
.filter(listener -> listener.getCriterionInstance().test(world, playerAdvancements))
.forEach(winner -> winner.grantCriterion(advancement));;
}
}
}

View file

@ -0,0 +1,11 @@
package com.minelittlepony.unicopia.advancements;
import net.minecraft.advancements.CriteriaTriggers;
public class UAdvancements {
public static final BOHDeathTrigger BOH_DEATH = new BOHDeathTrigger();
public static void init() {
CriteriaTriggers.register(BOH_DEATH);
}
}

View file

@ -0,0 +1,104 @@
package com.minelittlepony.unicopia.inventory;
import java.util.List;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
public class ContainerOfHolding extends Container {
private final InventoryOfHolding inventory;
private final World world;
private ItemStack sourceStack;
public ContainerOfHolding(EntityPlayer player) {
world = player.world;
sourceStack = player.getHeldItem(EnumHand.MAIN_HAND);
inventory = InventoryOfHolding.getInventoryFromStack(sourceStack);
inventory.openInventory(player);
this.onContainerClosed(player);
final int LEFT_MARGIN = 8;
final int TOP_MARGIN = 18;
final int inventoryRows = (int)Math.ceil(inventory.getSizeInventory() / 9);
for (int i = 0; i < inventory.getSizeInventory(); i++) {
int slotX = i % 9;
int slotY = (int)Math.floor(i / 9);
addSlotToContainer(new SlotOfHolding(inventory, i, LEFT_MARGIN + slotX * 18, TOP_MARGIN + slotY * 18));
}
int hotbarY = TOP_MARGIN + (inventoryRows * 18) + 4;
for (int i = 0; i < 9; ++i) {
addSlotToContainer(new Slot(player.inventory, i, LEFT_MARGIN + i * 18, hotbarY));
}
}
@Override
public void onContainerClosed(EntityPlayer player) {
inventory.writeTostack(sourceStack);
inventory.closeInventory(player);
super.onContainerClosed(player);
}
@Override
public boolean canInteractWith(EntityPlayer playerIn) {
return true;
}
public List<EntityLiving> getEntities() {
return inventory.getEntities(world);
}
public ITextComponent getDisplayName() {
return inventory.getDisplayName();
}
@Override
public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) {
ItemStack resultingStack = ItemStack.EMPTY;
Slot slot = inventorySlots.get(index);
if (slot != null && slot.getHasStack()) {
ItemStack originalStack = slot.getStack();
resultingStack = originalStack.copy();
if (index < inventory.getSizeInventory()) {
if (!mergeItemStack(originalStack, inventory.getSizeInventory(), this.inventorySlots.size(), true)) {
return ItemStack.EMPTY;
}
} else if (!this.mergeItemStack(originalStack, 0, inventory.getSizeInventory(), false)) {
return ItemStack.EMPTY;
}
if (originalStack.isEmpty()) {
slot.putStack(ItemStack.EMPTY);
} else {
slot.onSlotChanged();
}
}
return resultingStack;
}
class SlotOfHolding extends Slot {
public SlotOfHolding(IInventory inventoryIn, int index, int xPosition, int yPosition) {
super(inventoryIn, index, xPosition, yPosition);
}
}
}

View file

@ -0,0 +1,244 @@
package com.minelittlepony.unicopia.inventory;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import com.minelittlepony.unicopia.InbtSerialisable;
import com.minelittlepony.unicopia.advancements.UAdvancements;
import com.minelittlepony.unicopia.item.IMagicalItem;
import com.minelittlepony.util.MagicalDamageSource;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEnderChest;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.gui.advancements.AdvancementState;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryBasic;
import net.minecraft.item.ItemShulkerBox;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class InventoryOfHolding extends InventoryBasic implements InbtSerialisable {
public static final int NBT_COMPOUND = 10;
public static final int MIN_SIZE = 18;
List<NBTTagCompound> entities;
private boolean entitiesLoaded = false;
List<EntityLiving> livingEntities = new ArrayList<>();
static InventoryOfHolding empty() {
List<ItemStack> items = new ArrayList<>();
List<NBTTagCompound> entities = new ArrayList<>();
return new InventoryOfHolding(items, entities);
}
public static InventoryOfHolding getInventoryFromStack(ItemStack stack) {
List<ItemStack> items = new ArrayList<>();
List<NBTTagCompound> entities = new ArrayList<>();
iterateContents(stack, (i, item) -> {
items.add(item);
return true;
}, tag -> {
entities.add((NBTTagCompound)tag);
});
return new InventoryOfHolding(items, entities);
}
public static void iterateContents(ItemStack stack, BiFunction<Integer, ItemStack, Boolean> itemConsumer, Consumer<NBTTagCompound> entityConsumer) {
if (stack.hasTagCompound() && stack.getTagCompound().hasKey("inventory")) {
NBTTagCompound compound = stack.getOrCreateSubCompound("inventory");
if (compound.hasKey("items")) {
NBTTagList list = compound.getTagList("items", NBT_COMPOUND);
for (int i = 0; i < list.tagCount(); i++) {
ItemStack item = new ItemStack(list.getCompoundTagAt(i));
if (!item.isEmpty()) {
if (!itemConsumer.apply(i, item)) {
break;
}
}
}
}
}
}
private InventoryOfHolding(List<ItemStack> items, List<NBTTagCompound> entities) {
super("unicopia.gui.title.bagofholding", false, items.size() + 9 - (items.size() % 9));
this.entities = entities;
for (int i = 0; i < items.size(); i++) {
setInventorySlotContents(i, items.get(i));
}
}
public List<EntityLiving> getEntities(World world) {
return livingEntities;
}
public <T extends TileEntity & IInventory> void addBlockEntity(World world, BlockPos pos, IBlockState state, T blockInventory) {
ItemStack blockStack = new ItemStack(state.getBlock(), 1, state.getBlock().damageDropped(state));
blockInventory.writeToNBT(blockStack.getOrCreateSubCompound("BlockEntityTag"));
for (int i = 0; i < blockInventory.getSizeInventory(); i++) {
ItemStack stack = blockInventory.getStackInSlot(i);
if (isIllegalItem(stack)) {
blockStack.getOrCreateSubCompound("inventory").setBoolean("invalid", true);
break;
}
}
encodeStackWeight(blockStack, getContentsTotalWorth(blockInventory));
world.removeTileEntity(pos);
world.setBlockState(pos, Blocks.AIR.getDefaultState());
addItem(blockStack);
world.playSound(null, pos, SoundEvents.UI_TOAST_IN, SoundCategory.PLAYERS, 3.5F, 0.25F);
}
public void addPrisoner(EntityLiving entity) {
getEntities(entity.world).add(entity);
NBTTagCompound compound = new NBTTagCompound();
compound.setString("id", EntityList.getKey(entity).toString());
entity.writeToNBT(compound);
entities.add(compound);
entity.setDead();
entity.playLivingSound();
entity.playSound(SoundEvents.UI_TOAST_IN, 3.5F, 0.25F);
}
public void addItem(EntityItem entity) {
addItem(entity.getItem());
entity.setDead();
entity.playSound(SoundEvents.UI_TOAST_IN, 3.5F, 0.25F);
}
@Override
public void closeInventory(EntityPlayer player) {
if (checkExplosionConditions()) {
if (player instanceof EntityPlayerMP) {
UAdvancements.BOH_DEATH.trigger((EntityPlayerMP)player);
}
player.attackEntityFrom(MagicalDamageSource.create("paradox"), 1000);
player.world.createExplosion(player, player.posX, player.posY, player.posZ, 5, true);
}
}
protected boolean checkExplosionConditions() {
for (int i = 0; i < getSizeInventory(); i++) {
if (isIllegalItem(getStackInSlot(i))) {
return true;
}
}
return false;
}
protected boolean isIllegalItem(ItemStack stack) {
NBTTagCompound compound = stack.getSubCompound("inventory");
return isIllegalBlock(Block.getBlockFromItem(stack.getItem()))
|| stack.getItem() instanceof ItemShulkerBox
|| (compound != null && compound.hasKey("invalid"))
|| (stack.getItem() instanceof IMagicalItem && ((IMagicalItem) stack.getItem()).hasInnerSpace());
}
protected boolean isIllegalBlock(Block block) {
return block instanceof BlockEnderChest;
}
@Override
public void writeToNBT(NBTTagCompound compound) {
NBTTagList nbtItems = new NBTTagList();
for (int i = 0; i < getSizeInventory(); i++) {
NBTTagCompound comp = new NBTTagCompound();
ItemStack stack = getStackInSlot(i);
if (!isIllegalItem(stack)) {
if (!stack.isEmpty()) {
stack.writeToNBT(comp);
nbtItems.appendTag(comp);
}
}
}
compound.setTag("items", nbtItems);
compound.setDouble("weight", getContentsTotalWorth());
}
public double getContentsTotalWorth() {
return getContentsTotalWorth(this);
}
public void writeTostack(ItemStack stack) {
writeToNBT(stack.getOrCreateSubCompound("inventory"));
}
public static double getContentsTotalWorth(IInventory inventory) {
double total = 0;
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack stack = inventory.getStackInSlot(i);
total += stack.getCount();
total += decodeStackWeight(stack);
}
return total;
}
public static void encodeStackWeight(ItemStack stack, double weight) {
NBTTagCompound compound = stack.getSubCompound("inventory");
if (weight == 0 && compound != null) {
compound.removeTag("weight");
if (compound.isEmpty()) {
stack.removeSubCompound("inventory");
}
} else {
if (weight != 0) {
if (compound == null) {
compound = stack.getOrCreateSubCompound("inventory");
}
compound.setDouble("weight", weight);
}
}
}
public static double decodeStackWeight(ItemStack stack) {
if (!stack.isEmpty()) {
NBTTagCompound compound = stack.getSubCompound("inventory");
if (compound != null && compound.hasKey("weight")) {
return compound.getDouble("weight");
}
}
return 0;
}
}

View file

@ -0,0 +1,129 @@
package com.minelittlepony.unicopia.inventory.gui;
import java.io.IOException;
import com.minelittlepony.unicopia.inventory.ContainerOfHolding;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.EntityLiving;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.IInteractionObject;
public class GuiOfHolding extends GuiContainer {
private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("textures/gui/container/generic_54.png");
private final int inventoryRows;
private final Scrollbar scrollbar = new Scrollbar();
public GuiOfHolding(IInteractionObject interaction) {
super(interaction.createContainer(Minecraft.getMinecraft().player.inventory, Minecraft.getMinecraft().player));
inventoryRows = (inventorySlots.inventorySlots.size() / 9) - 1;
}
@Override
public void initGui() {
super.initGui();
scrollbar.reposition(
guiLeft + xSize,
guiTop,
ySize,
(inventoryRows + 1) * 18 + 17);
}
@Override
public void onGuiClosed() {
super.onGuiClosed();
mc.player.playSound(SoundEvents.BLOCK_ENDERCHEST_OPEN, 0.5F, 0.5F);
}
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
drawDefaultBackground();
scrollbar.render(mouseX, mouseY, partialTicks);
int scroll = -scrollbar.getScrollAmount();
GlStateManager.pushMatrix();
GlStateManager.translate(0, scroll, 0);
super.drawScreen(mouseX, mouseY - scroll, partialTicks);
int h = height;
height = Integer.MAX_VALUE;
renderHoveredToolTip(mouseX, mouseY - scroll);
height = h;
GlStateManager.popMatrix();
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
scrollbar.performAction(mouseX, mouseY);
super.mouseClicked(mouseX, mouseY + scrollbar.getScrollAmount(), mouseButton);
}
@Override
protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
super.mouseClickMove(mouseX, mouseY + scrollbar.getScrollAmount(), clickedMouseButton, timeSinceLastClick);
if (!dragSplitting) {
scrollbar.mouseMove(mouseX, mouseY, timeSinceLastClick);
}
}
@Override
protected void mouseReleased(int mouseX, int mouseY, int state) {
super.mouseReleased(mouseX, mouseY + scrollbar.getScrollAmount(), state);
scrollbar.mouseUp(mouseX, mouseY);
}
@Override
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
ContainerOfHolding coh = (ContainerOfHolding)inventorySlots;
fontRenderer.drawString(coh.getDisplayName().getUnformattedText(), 8, 6, 4210752);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
GlStateManager.color(1, 1, 1, 1);
mc.getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
int midX = (width - xSize) / 2;
int midY = (height - ySize) / 2;
drawTexturedModalRect(midX, midY, 0, 0, xSize, 18);
for (int i = 0; i < inventoryRows; i++) {
drawTexturedModalRect(midX, midY + (18 * (i + 1)), 0, 18, xSize, 18);
}
drawTexturedModalRect(midX, midY + inventoryRows * 18 + 17, 0, 193, xSize, 30);
ContainerOfHolding coh = (ContainerOfHolding)inventorySlots;
int left = (width - xSize) / 2;
int top = (height - ySize) / 2;
int i = 0;
for (EntityLiving entity : coh.getEntities()) {
int x = i % 9;
int y = i / 9;
GuiInventory.drawEntityOnScreen(left + x * 18, top + y * 30, 18, xSize - mouseX, guiTop + 30 - mouseY, entity);
i++;
}
}
}

View file

@ -0,0 +1,212 @@
package com.minelittlepony.unicopia.inventory.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.math.MathHelper;
public class Scrollbar {
private boolean dragging = false;
private boolean touching = false;
private int scrollY = 0;
private int thickness = 6;
private float scrollMomentum = 0;
private float scrollFactor = 0;
private int maxScrollY = 0;
private int shiftFactor = 0;
private int elementHeight;
private int contentHeight;
private int x;
private int y;
private int initialMouseY;
public Scrollbar() {
}
public void reposition(int x, int y, int elementHeight, int contentHeight) {
this.x = x;
this.y = y;
this.elementHeight = elementHeight;
this.contentHeight = contentHeight;
maxScrollY = contentHeight - elementHeight;
if (maxScrollY < 0) {
maxScrollY = 0;
}
scrollFactor = elementHeight == 0 ? 1 : contentHeight / elementHeight;
scrollBy(0);
}
public int getScrollAmount() {
return scrollY;
}
public void render(int mouseX, int mouseY, float partialTicks) {
if (!touching && !dragging) {
scrollMomentum *= partialTicks;
if (scrollMomentum > 0) {
scrollBy(scrollMomentum);
}
if (shiftFactor != 0) {
scrollBy(shiftFactor * scrollFactor);
shiftFactor = computeShiftFactor(mouseX, mouseY);
}
}
if (maxScrollY <= 0) return;
renderVertical();
}
protected void renderVertical() {
int scrollbarHeight = getScrubberLength(elementHeight, contentHeight);
int scrollbarTop = getScrubberStart(scrollbarHeight, elementHeight, contentHeight);
renderBackground(y, x, y + elementHeight, x + thickness);
renderBar(x, x + thickness, scrollbarTop, scrollbarTop + scrollbarHeight);
}
protected int getScrubberStart(int scrollbarHeight, int elementHeight, int contentHeight) {
if (maxScrollY == 0) {
return 0;
}
int scrollbarTop = y + getScrollAmount() * (elementHeight - scrollbarHeight) / maxScrollY;
if (scrollbarTop < 0) {
return 0;
}
return scrollbarTop;
}
protected int getScrubberLength(int elementL, int contentL) {
return MathHelper.clamp(elementL * elementL / contentL, 32, elementL - 8);
}
public boolean isFocused(int mouseX, int mouseY) {
return mouseY >= y
&& mouseY <= y + elementHeight
&& mouseX >= (x - 10)
&& mouseX <= (x + thickness + 1);
}
private void renderBackground(int top, int left, int bottom, int right) {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
GlStateManager.color(1, 1, 1, 1);
GlStateManager.disableTexture2D();
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
GlStateManager.disableAlpha();
GlStateManager.shadeModel(7425);
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos(left, bottom, 0).tex(0, 1).color(0, 0, 0, 150).endVertex();
bufferbuilder.pos(right, bottom, 0).tex(1, 1).color(0, 0, 0, 150).endVertex();
bufferbuilder.pos(right, top, 0).tex(1, 0).color(0, 0, 0, 150).endVertex();
bufferbuilder.pos(left, top, 0).tex(0, 0).color(0, 0, 0, 150).endVertex();
tessellator.draw();
GlStateManager.shadeModel(7424);
GlStateManager.enableAlpha();
GlStateManager.disableBlend();
}
private void renderBar(int left, int right, int top, int bottom) {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
GlStateManager.color(1, 1, 1, 1);
GlStateManager.disableTexture2D();
int B = dragging ? 170 : 128;
int b = dragging ? 252 : 192;
//actual bar
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos(left, bottom, 0).tex(0, 1).color(128, 128, B, 255).endVertex();
bufferbuilder.pos(right, bottom, 0).tex(1, 1).color(128, 128, B, 255).endVertex();
bufferbuilder.pos(right, top, 0).tex(1, 0).color(128, 128, B, 255).endVertex();
bufferbuilder.pos(left, top, 0).tex(0, 0).color(128, 128, B, 255).endVertex();
tessellator.draw();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos(left, bottom - 1, 0).tex(0, 1).color(192, 192, b, 255).endVertex();
bufferbuilder.pos(right - 1, bottom - 1, 0).tex(1, 1).color(192, b, 192, 255).endVertex();
bufferbuilder.pos(right - 1, top, 0).tex(1, 0).color(192, 192, b, 255).endVertex();
bufferbuilder.pos(left, top, 0.0D).tex(0, 0).color(192, 192, b, 255).endVertex();
tessellator.draw();
GlStateManager.enableTexture2D();
}
private int computeShiftFactor(int mouseX, int mouseY) {
int pos = mouseY;
int scrubberLength = getScrubberLength(elementHeight, contentHeight);
int scrubberStart = getScrubberStart(scrubberLength, elementHeight, contentHeight);
if (pos < scrubberStart) {
return 1;
} else if (pos > scrubberStart + scrubberLength) {
return -1;
}
return 0;
}
public boolean performAction(int mouseX, int mouseY) {
if (!isFocused(mouseX, mouseY)) {
touching = true;
return true;
}
shiftFactor = computeShiftFactor(mouseX, mouseY);
if (shiftFactor == 0) {
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1));
dragging = true;
}
return true;
}
public void mouseMove(int mouseX, int mouseY, float partialTicks) {
if (dragging) {
scrollBy(initialMouseY - mouseY);
} else if (touching) {
scrollMomentum = mouseY - initialMouseY;
scrollBy((mouseY - initialMouseY) / 4);
}
initialMouseY = mouseY;
}
public void mouseUp(int mouseX, int mouseY) {
dragging = touching = false;
shiftFactor = 0;
}
public void scrollBy(float y) {
scrollY = MathHelper.clamp((int)Math.floor(scrollY - y * scrollFactor), 0, maxScrollY);
}
}

View file

@ -0,0 +1,11 @@
package com.minelittlepony.unicopia.item;
public interface IMagicalItem {
/**
* If true this item serves as host to its own inner dimensional space.
* Bag of Holding will explode if you try to store items of this kind inside of it.
*/
default boolean hasInnerSpace() {
return false;
}
}

View file

@ -0,0 +1,180 @@
package com.minelittlepony.unicopia.item;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Predicates;
import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.inventory.ContainerOfHolding;
import com.minelittlepony.unicopia.inventory.InventoryOfHolding;
import com.minelittlepony.unicopia.inventory.gui.GuiOfHolding;
import com.minelittlepony.util.vector.VecHelper;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.IInteractionObject;
import net.minecraft.world.World;
public class ItemOfHolding extends Item implements IMagicalItem {
public ItemOfHolding(String domain, String name) {
setCreativeTab(CreativeTabs.TRANSPORTATION);
setTranslationKey(name);
setRegistryName(domain, name);
setMaxStackSize(1);
}
@Override
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
super.addInformation(stack, worldIn, tooltip, flagIn);
Map<String, Integer> counts = new HashMap<>();
InventoryOfHolding.iterateContents(stack, (i, itemstack) -> {
String name = itemstack.getDisplayName();
counts.put(name, counts.getOrDefault(name, 0) + itemstack.getCount());
return true;
}, tag -> {
String name = tag.getString("id");
counts.put(name, counts.getOrDefault(name, 0) + 1);
});
for (String name : counts.keySet()) {
tooltip.add(String.format("%s x%d", name, counts.get(name)));
}
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (!Predicates.MAGI.test(player)) {
return super.onItemRightClick(world, player, hand);
}
ItemStack stack = player.getHeldItem(hand);
if (player.isSneaking()) {
RayTraceResult hit = VecHelper.getObjectMouseOver(player, 5, 0);
if (hit != null) {
if (hit.typeOfHit == RayTraceResult.Type.BLOCK) {
BlockPos pos = hit.getBlockPos();
IBlockState state = world.getBlockState(pos);
TileEntity tile = world.getTileEntity(pos);
if (tile instanceof IInventory) {
InventoryOfHolding inventory = InventoryOfHolding.getInventoryFromStack(stack);
inventory.addBlockEntity(world, pos, state, (TileEntity & IInventory)tile);
inventory.writeTostack(stack);
inventory.closeInventory(player);
return new ActionResult<>(EnumActionResult.SUCCESS, stack);
}
AxisAlignedBB box = new AxisAlignedBB(pos.offset(hit.sideHit)).grow(0.5);
List<Entity> itemsAround = world.getEntitiesInAABBexcluding(player, box, e -> e.isEntityAlive() && e instanceof EntityItem);
if (itemsAround.size() > 0) {
InventoryOfHolding inventory = InventoryOfHolding.getInventoryFromStack(stack);
inventory.addItem((EntityItem)itemsAround.get(0));
inventory.writeTostack(stack);
inventory.closeInventory(player);
return new ActionResult<>(EnumActionResult.SUCCESS, stack);
}
} else if (hit.typeOfHit == RayTraceResult.Type.ENTITY && hit.entityHit instanceof EntityLiving) {
/*if (!(hit.entityHit instanceof EntityPlayer)) {
InventoryOfHolding inventory = InventoryOfHolding.getInventoryFromStack(stack);
inventory.addPrisoner((EntityLiving)hit.entityHit);
inventory.writeTostack(stack);
inventory.closeInventory(player);
return new ActionResult<>(EnumActionResult.SUCCESS, stack);
}*/
}
}
return new ActionResult<>(EnumActionResult.FAIL, stack);
} else {
IInteractionObject inventory = new Inventory();
if (UClient.isClientSide() && player instanceof EntityPlayerSP) {
Minecraft.getMinecraft().displayGuiScreen(new GuiOfHolding(inventory));
player.playSound(SoundEvents.BLOCK_ENDERCHEST_OPEN, 0.5F, 1);
} else {
player.displayGui(inventory);
}
return new ActionResult<>(EnumActionResult.SUCCESS, stack);
}
}
public class Inventory implements IInteractionObject {
@Override
public String getName() {
return "unicopi.gui.title.itemofholding";
}
@Override
public boolean hasCustomName() {
return false;
}
@Override
public ITextComponent getDisplayName() {
return new TextComponentTranslation(getName());
}
@Override
public Container createContainer(InventoryPlayer playerInventory, EntityPlayer player) {
return new ContainerOfHolding(player);
}
@Override
public String getGuiID() {
return "unicopia:itemofholding";
}
}
@Override
public boolean hasInnerSpace() {
return true;
}
}

View file

@ -3,30 +3,43 @@ package com.minelittlepony.unicopia.player;
import java.util.UUID; import java.util.UUID;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.inventory.InventoryOfHolding;
import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttribute; import net.minecraft.entity.ai.attributes.IAttribute;
import net.minecraft.entity.ai.attributes.IAttributeInstance; import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
class PlayerAttributes { class PlayerAttributes {
public static final int ADD = 0; public static final int ADD = 0;
public static final int ADD_PERCENTAGE = 1; public static final int ADD_PERCENTAGE = 1;
public static final int MULTIPLY = 2; public static final int MULTIPLY = 2;
public static final PlayerAttributes instance = new PlayerAttributes(); private static final AttributeModifier EARTH_PONY_STRENGTH =
private final AttributeModifier EARTH_PONY_STRENGTH =
new AttributeModifier(UUID.fromString("777a5505-521e-480b-b9d5-6ea54f259564"), "Earth Pony Strength", 0.6, MULTIPLY); new AttributeModifier(UUID.fromString("777a5505-521e-480b-b9d5-6ea54f259564"), "Earth Pony Strength", 0.6, MULTIPLY);
private final AttributeModifier PEGASUS_SPEED = private static final AttributeModifier PEGASUS_SPEED =
new AttributeModifier(UUID.fromString("9e2699fc-3b8d-4f71-9d2d-fb92ee19b4f7"), "Pegasus Speed", 0.2, MULTIPLY); new AttributeModifier(UUID.fromString("9e2699fc-3b8d-4f71-9d2d-fb92ee19b4f7"), "Pegasus Speed", 0.2, MULTIPLY);
private final AttributeModifier PEGASUS_REACH = private static final AttributeModifier PEGASUS_REACH =
new AttributeModifier(UUID.fromString("707b50a8-03e8-40f4-8553-ecf67025fd6d"), "Pegasus Reach", 1.5, ADD); new AttributeModifier(UUID.fromString("707b50a8-03e8-40f4-8553-ecf67025fd6d"), "Pegasus Reach", 1.5, ADD);
private double loadStrength = 0;
public void applyAttributes(EntityPlayer entity, Race race) { public void applyAttributes(EntityPlayer entity, Race race) {
loadStrength = 0;
for (ItemStack item : entity.inventory.mainInventory) {
loadStrength += InventoryOfHolding.decodeStackWeight(item);
}
for (ItemStack item : entity.inventory.armorInventory) {
loadStrength += InventoryOfHolding.decodeStackWeight(item);
}
entity.capabilities.setPlayerWalkSpeed(0.1F - (float)(loadStrength / 100000));
applyAttribute(entity, SharedMonsterAttributes.ATTACK_DAMAGE, EARTH_PONY_STRENGTH, race.canUseEarth()); applyAttribute(entity, SharedMonsterAttributes.ATTACK_DAMAGE, EARTH_PONY_STRENGTH, race.canUseEarth());
applyAttribute(entity, SharedMonsterAttributes.KNOCKBACK_RESISTANCE, EARTH_PONY_STRENGTH, race.canUseEarth()); applyAttribute(entity, SharedMonsterAttributes.KNOCKBACK_RESISTANCE, EARTH_PONY_STRENGTH, race.canUseEarth());
applyAttribute(entity, SharedMonsterAttributes.MOVEMENT_SPEED, PEGASUS_SPEED, race.canFly()); applyAttribute(entity, SharedMonsterAttributes.MOVEMENT_SPEED, PEGASUS_SPEED, race.canFly());

View file

@ -36,6 +36,8 @@ class PlayerCapabilities implements IPlayer, ICaster<EntityPlayer> {
private final PlayerGravityDelegate gravity = new PlayerGravityDelegate(this); private final PlayerGravityDelegate gravity = new PlayerGravityDelegate(this);
private final PlayerAttributes attributes = new PlayerAttributes();
private float nextStepDistance = 1; private float nextStepDistance = 1;
private IMagicEffect effect; private IMagicEffect effect;
@ -131,7 +133,7 @@ class PlayerCapabilities implements IPlayer, ICaster<EntityPlayer> {
addExertion(-1); addExertion(-1);
PlayerAttributes.instance.applyAttributes(entity, getPlayerSpecies()); attributes.applyAttributes(entity, getPlayerSpecies());
} }
@Override @Override

View file

@ -0,0 +1,87 @@
package com.minelittlepony.util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* All of the Auxiliary effects used in minecraft for World.spawnEvent
*/
public enum WorldEvent {
DISPENSER_DISPENSE_BLOCK(1000),
DISPENSER_FAIL(1001),
DISPENSE_SHOOT_PROJECTILE(1002),
LAUNCH_ENDER_PEAR(1003),
LAUNCH_FIREWORKS_ROCKET(1004),
RECORD_DROP(1005), IRON_DOOR_OPEN(1005),
WOODEN_DOOR_OPEN(1006),
WOODEN_TRAPDOOR_OPEN(1007),
GATE_OPEN(1008),
FIRE_EXTENGUISH(1009),
PLAY_RECORD(1010),
IRON_DOOR_SLAM(1011),
WOODEN_DOOR_SLAM(1012),
WOODEN_TRAPDOOR_SLAM(1013),
FENCE_GATE_SWIVEL(1014),
GHAST_SCREAM(1015),
GHAST_SHOOT(1016),
ENDERMAN_SCREAM(1017),
FIRE_SHOOT(1018),
DOOR_SWIVEL(1019), WOOD_DOOR_KNOCK(1019),
REPAIR_ITEM(1020), IRON_DOOR_KNOCK(1020),
DOOR_BROKEN(1021),
WITHER_ATTACK(1022),
WITHER_SHOOT(1024),
ENTITY_TAKEOFF(1025),
MOB_INFECT(1026),
MOB_CURE(1027),
ANVIL_DESTROY(1029),
ANVIL_USE(1030),
ANVIL_LAND(1031),
PORTAL_WARP(1032),
ORGANIC_WET(1033),
ORGANIC_DRY(1034),
BREW_POTION(1035),
DOOR_CLOSE(1036),
DOOR_OPEN(1037),
DISPENSE_PARTICLES(2000),
DESTROY_BLOCK(2001),
XP_POP(2002), PROJECTILE_HIT(2002),
EYE_OF_ENDER(2003),
MOB_SPAWN(2004),
BONEMEAN(2005),
DRAGON_BREATH(2006),
POTION_INSTANT(2007),
DRAGON_DEFEATED(3000),
DRAGON_ROARS(3001),
UNKNOWN(0);
private final int id;
WorldEvent(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void play(World world, BlockPos pos, int data) {
world.playEvent(getId(), pos, data);
}
public static WorldEvent fromId(int id) {
for (WorldEvent i : values()) {
if (i.id == id) {
return i;
}
}
return UNKNOWN;
}
}

View file

@ -0,0 +1,23 @@
{
"display": {
"icon": {
"item": "unicopia:bag_of_holding"
},
"title": {
"translate": "advancements.adventure.bag_of_holding.title"
},
"description": {
"translate": "advancements.adventure.bag_of_holding.description"
},
"frame": "challenge"
},
"parent": "minecraft:adventure/root",
"criteria": {
"death_by_bag_of_holding": {
"trigger": "unicopia:death_by_bag_of_holding",
"conditions": {
"advancement": "minecraft:adventure/root"
}
}
}
}

View file

@ -0,0 +1,23 @@
{
"display": {
"icon": {
"item": "unicopia:bag_of_holding"
},
"title": {
"translate": "advancements.adventure.bag_of_holding_2.title"
},
"description": {
"translate": "advancements.adventure.bag_of_holding_2.description"
},
"frame": "challenge"
},
"parent": "unicopia:bag_of_holding",
"criteria": {
"death_by_bag_of_holding": {
"trigger": "unicopia:death_by_bag_of_holding",
"conditions": {
"advancement": "unicopia:bag_of_holding"
}
}
}
}

View file

@ -0,0 +1,23 @@
{
"display": {
"icon": {
"item": "unicopia:bag_of_holding"
},
"title": {
"translate": "advancements.adventure.bag_of_holding_3.title"
},
"description": {
"translate": "advancements.adventure.bag_of_holding_3.description"
},
"frame": "challenge"
},
"parent": "unicopia:bag_of_holding_2",
"criteria": {
"death_by_bag_of_holding": {
"trigger": "unicopia:death_by_bag_of_holding",
"conditions": {
"advancement": "unicopia:bag_of_holding_2"
}
}
}
}

View file

@ -13,6 +13,10 @@ item.cloud.small.name=Bucking Bronco
item.cloud.medium.name=Construction Cloud item.cloud.medium.name=Construction Cloud
item.cloud.large.name=Wild Cloud item.cloud.large.name=Wild Cloud
item.mist_door.name=Cloud Door
item.dew_drop.name=Dew Drop
item.cloud_anvil.name=Anvilhead Anvil
item.spell.name=Gem item.spell.name=Gem
item.spell.shield.name=Gem of Repulsion item.spell.shield.name=Gem of Repulsion
item.spell.fire.name=Gem of Flame item.spell.fire.name=Gem of Flame
@ -22,6 +26,7 @@ item.spell.portal.name=Gem of Teleportation
item.spell.attract.name=Gem of Retention item.spell.attract.name=Gem of Retention
item.spell.minion.name=Gem of Obedience item.spell.minion.name=Gem of Obedience
item.spellbook.name=Spellbook item.spellbook.name=Spellbook
item.bag_of_holding.name=Bag of Holding
item.apple.green.name=Granny Smith Apple item.apple.green.name=Granny Smith Apple
item.apple.sweet.name=Sweet Apple Acres Apple item.apple.sweet.name=Sweet Apple Acres Apple
@ -31,7 +36,7 @@ item.apple.zap_cooked.name=Cooked Zap Apple
entity.racing_cloud.name=Bucking Bronco entity.racing_cloud.name=Bucking Bronco
entity.construction_cloud.name=Construction Cloud entity.construction_cloud.name=Construction Cloud
entity.wild_cloud.name=Cloud entity.cloud.name=Cloud
entity.spell.name=Magic entity.spell.name=Magic
@ -102,6 +107,8 @@ unicopia.power.thunder=Secondary Pegasus ability
unicopia.power.feed=Primary Changeling ability unicopia.power.feed=Primary Changeling ability
unicopia.power.disguise=Secondary Changeling ability unicopia.power.disguise=Secondary Changeling ability
unicopia.gui.title.bagofholding=Bag of Holding
death.attack.feed=%1$s was drained of all life death.attack.feed=%1$s was drained of all life
death.attack.feed.player=%1$s died to feed %2$s death.attack.feed.player=%1$s died to feed %2$s
death.attack.cold=%1$s died of frost bite death.attack.cold=%1$s died of frost bite
@ -113,3 +120,13 @@ death.attack.fire=%1$s was burnt to a crisp by magic
death.attack.fire.player=%1$s was burnt to a crisp by %2$s death.attack.fire.player=%1$s was burnt to a crisp by %2$s
death.attack.fire.own=%1$s was burnt to a crisp by their own spell death.attack.fire.own=%1$s was burnt to a crisp by their own spell
death.attack.zap=%1$s ate a Zap Apple death.attack.zap=%1$s ate a Zap Apple
death.attack.paradox=%1$s imploded
advancements.adventure.bag_of_holding.title=Read the Manual
advancements.adventure.bag_of_holding.description=Successfuly die using the Bag of Holding
advancements.adventure.bag_of_holding_2.title=Oops! I did it again
advancements.adventure.bag_of_holding_2.description=Die by the Bag of Holding a second time
advancements.adventure.bag_of_holding_3.title=Oh come on!
advancements.adventure.bag_of_holding_3.description=-_-

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "unicopia:items/bag_o"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB