mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Add the bag of holding
This commit is contained in:
parent
bcb0ee9f75
commit
0cb646bb56
19 changed files with 1243 additions and 10 deletions
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
|
87
src/main/java/com/minelittlepony/util/WorldEvent.java
Normal file
87
src/main/java/com/minelittlepony/util/WorldEvent.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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=-_-
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:items/bag_o"
|
||||||
|
}
|
||||||
|
}
|
BIN
src/main/resources/assets/unicopia/textures/items/bag_o.png
Normal file
BIN
src/main/resources/assets/unicopia/textures/items/bag_o.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3 KiB |
Loading…
Reference in a new issue