diff --git a/src/main/java/com/minelittlepony/unicopia/UEntities.java b/src/main/java/com/minelittlepony/unicopia/UEntities.java index b58fd7a7..599c2354 100644 --- a/src/main/java/com/minelittlepony/unicopia/UEntities.java +++ b/src/main/java/com/minelittlepony/unicopia/UEntities.java @@ -4,11 +4,13 @@ import com.minelittlepony.unicopia.entity.EntityCloud; import com.minelittlepony.unicopia.entity.EntityConstructionCloud; import com.minelittlepony.unicopia.entity.EntityRacingCloud; import com.minelittlepony.unicopia.entity.EntitySpell; +import com.minelittlepony.unicopia.entity.EntitySpellbook; import com.minelittlepony.unicopia.entity.EntityProjectile; import com.minelittlepony.unicopia.entity.EntityWildCloud; import com.minelittlepony.unicopia.render.RenderCloud; import com.minelittlepony.unicopia.render.RenderGem; import com.minelittlepony.unicopia.render.RenderProjectile; +import com.minelittlepony.unicopia.render.RenderSpellbook; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityList.EntityEggInfo; @@ -29,6 +31,7 @@ public class UEntities { new Entry(EntityRacingCloud.class, "racing_cloud"), new Entry(EntityConstructionCloud.class, "construction_cloud"), new Entry(EntitySpell.class, "magic_spell"), + new Entry(EntitySpellbook.class, "spellbook"), EntityEntryBuilder.create().entity(EntityProjectile.class).name("thrown_item").id(new ResourceLocation(Unicopia.MODID, "thrown_item"), 0).tracker(10, 5, true).build() ); } @@ -37,6 +40,7 @@ public class UEntities { RenderingRegistry.registerEntityRenderingHandler(EntityCloud.class, RenderCloud::new); RenderingRegistry.registerEntityRenderingHandler(EntitySpell.class, RenderGem::new); RenderingRegistry.registerEntityRenderingHandler(EntityProjectile.class, RenderProjectile::new); + RenderingRegistry.registerEntityRenderingHandler(EntitySpellbook.class, RenderSpellbook::new); } static class Entry extends EntityEntry { diff --git a/src/main/java/com/minelittlepony/unicopia/UItems.java b/src/main/java/com/minelittlepony/unicopia/UItems.java index e52babff..9d301ab7 100644 --- a/src/main/java/com/minelittlepony/unicopia/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/UItems.java @@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.item.ItemCloud; import com.minelittlepony.unicopia.item.ItemCurse; import com.minelittlepony.unicopia.item.ItemOfHolding; import com.minelittlepony.unicopia.item.ItemSpell; +import com.minelittlepony.unicopia.item.ItemSpellbook; import com.minelittlepony.unicopia.item.ItemStick; import com.minelittlepony.unicopia.item.ItemTomato; import com.minelittlepony.unicopia.item.ItemTomatoSeeds; @@ -90,6 +91,8 @@ public class UItems { public static final ItemOfHolding bag_of_holding = new ItemOfHolding(Unicopia.MODID, "bag_of_holding"); + public static final ItemSpellbook spellbook = new ItemSpellbook(Unicopia.MODID, "spellbook"); + public static final Item alfalfa_seeds = new ItemSeedFood(1, 4, UBlocks.alfalfa, Blocks.FARMLAND) .setTranslationKey("alfalfa_seeds") .setRegistryName(Unicopia.MODID, "alfalfa_seeds") @@ -119,7 +122,9 @@ public class UItems { registry.registerAll(cloud_spawner, dew_drop, cloud_matter, cloud_block, cloud_stairs, cloud_slab, cloud_farmland, mist_door, anvil, - bag_of_holding, spell, curse, + + bag_of_holding, spell, curse, spellbook, + alfalfa_seeds, alfalfa_leaves, cereal, sugar_cereal, sugar_block, @@ -139,6 +144,7 @@ public class UItems { registerAllVariants(bag_of_holding, "bag_of_holding"); registerAllVariants(spell, "gem"); registerAllVariants(curse, "corrupted_gem"); + registerAllVariants(spellbook, "spellbook"); registerAllVariants(alfalfa_seeds, "alfalfa_seeds"); registerAllVariants(alfalfa_leaves, "alfalfa_leaves"); registerAllVariants(cereal, "cereal"); diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpellbook.java b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpellbook.java new file mode 100644 index 00000000..0caf39f7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpellbook.java @@ -0,0 +1,166 @@ +package com.minelittlepony.unicopia.entity; + +import com.minelittlepony.unicopia.Predicates; +import com.minelittlepony.unicopia.UItems; + +import net.minecraft.block.SoundType; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +public class EntitySpellbook extends EntityLiving implements IMagicals { + + private static final DataParameter OPENED = EntityDataManager.createKey(EntitySpellbook.class, DataSerializers.BOOLEAN); + private static final DataParameter OPENED_USER = EntityDataManager.createKey(EntitySpellbook.class, DataSerializers.BYTE); + + public EntitySpellbook(World worldIn) { + super(worldIn); + setSize(0.6f, 0.6f); + } + + @Override + protected void entityInit() { + super.entityInit(); + dataManager.register(OPENED, true); + dataManager.register(OPENED_USER, (byte)1); + } + + @Override + protected boolean canTriggerWalking() { + return false; + } + + @Override + public boolean isPushedByWater() { + return false; + } + + @Override + public boolean canRenderOnFire() { + return false; + } + + public boolean getIsOpen() { + return dataManager.get(OPENED); + } + + public Boolean getUserSetState() { + byte state = dataManager.get(OPENED_USER); + return state == 1 ? null : state == 2; + } + + public void setIsOpen(boolean val) { + dataManager.set(OPENED, val); + } + + public void setUserSetState(Boolean val) { + dataManager.set(OPENED_USER, val == null ? (byte)1 : val == true ? (byte)2 : (byte)0); + } + + @Override + public void onUpdate() { + boolean open = getIsOpen(); + this.isJumping = open && isInWater(); + super.onUpdate(); + if (open && world.isRemote) { + for (int offX = -2; offX <= 1; ++offX) { + for (int offZ = -2; offZ <= 1; ++offZ) { + if (offX > -1 && offX < 1 && offZ == -1) offZ = 1; + if (rand.nextInt(320) == 0) { + for (int offY = 0; offY <= 1; ++offY) { + float vX = (float)offX/2 + rand.nextFloat(); + float vY = (float)offY/2 - rand.nextFloat() + 0.5f; + float vZ = (float)offZ/2 + rand.nextFloat(); + world.spawnParticle(EnumParticleTypes.ENCHANTMENT_TABLE, posX, posY, posZ, vX, vY, vZ, new int[0]); + } + } + } + } + } + + if (world.rand.nextInt(30) == 0) { + float celest = world.getCelestialAngle(1) * 4; + boolean isDay = celest > 3 || celest < 1; + Boolean userState = getUserSetState(); + boolean canToggle = (isDay != open) && (userState == null || userState == isDay); + if (canToggle) { + setUserSetState(null); + setIsOpen(isDay); + } + if (userState != null && (isDay == open) && (userState == open)) { + setUserSetState(null); + } + } + } + + @Override + public boolean attackEntityFrom(DamageSource source, float amount) { + if (!world.isRemote) { + setDead(); + SoundType sound = SoundType.WOOD; + world.playSound(posX, posY, posZ, sound.getBreakSound(), SoundCategory.BLOCKS, sound.getVolume(), sound.getPitch(), true); + if (world.getGameRules().getBoolean("doTileDrops")) { + entityDropItem(new ItemStack(UItems.spellbook, 1), 0); + } + } + return false; + } + + @Override + public EnumActionResult applyPlayerInteraction(EntityPlayer player, Vec3d vec, EnumHand hand) { + if (player.isSneaking()) { + boolean open = !getIsOpen(); + + setIsOpen(open); + setUserSetState(open); + + return EnumActionResult.SUCCESS; + } + + if (Predicates.MAGI.test(player)) { + //ApiGui.openContainer((EntityPlayerMP)player, new InterfaceBook()); + + return EnumActionResult.SUCCESS; + } + + return EnumActionResult.PASS; + } + + @Override + public void readEntityFromNBT(NBTTagCompound compound) { + super.readEntityFromNBT(compound); + setIsOpen(compound.getBoolean("open")); + if (compound.hasKey("force_open")) { + setUserSetState(compound.getBoolean("force_open")); + } else { + setUserSetState(null); + } + } + + @Override + public void writeEntityToNBT(NBTTagCompound compound) { + super.writeEntityToNBT(compound); + compound.setBoolean("open", getIsOpen()); + Boolean state = getUserSetState(); + if (state != null) { + compound.setBoolean("force_open", state); + } + } + + @Override + public ItemStack getPickedResult(RayTraceResult target) { + return new ItemStack(UItems.spellbook); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemSpellbook.java b/src/main/java/com/minelittlepony/unicopia/item/ItemSpellbook.java new file mode 100644 index 00000000..f1737de0 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemSpellbook.java @@ -0,0 +1,104 @@ +package com.minelittlepony.unicopia.item; + +import com.minelittlepony.unicopia.Predicates; +import com.minelittlepony.unicopia.entity.EntitySpellbook; + +import net.minecraft.block.BlockDispenser; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.dispenser.BehaviorDefaultDispenseItem; +import net.minecraft.dispenser.IBehaviorDispenseItem; +import net.minecraft.dispenser.IBlockSource; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBook; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ItemSpellbook extends ItemBook { + private static final IBehaviorDispenseItem dispenserBehavior = new BehaviorDefaultDispenseItem() { + @Override + protected ItemStack dispenseStack(IBlockSource source, ItemStack stack) { + EnumFacing facing = source.getBlockState().getValue(BlockDispenser.FACING); + BlockPos pos = source.getBlockPos().offset(facing); + int yaw = 0; + + + //0deg == SOUTH + //90deg == WEST + //180deg == NORTH + //270deg == EAST + + /*switch (facing) { + case NORTH: yaw -= 90; break; + case SOUTH: yaw += 90; break; + case EAST: yaw += 180; break; + default: + }*/ + + yaw = facing.getOpposite().getHorizontalIndex() * 90; + placeBook(source.getWorld(), pos.getX(), pos.getY(), pos.getZ(), yaw); + stack.shrink(1); + return stack; + } + }; + + public ItemSpellbook(String domain, String name) { + super(); + setTranslationKey(name); + setRegistryName(domain, name); + + setMaxDamage(0); + maxStackSize = 1; + setCreativeTab(CreativeTabs.BREWING); + BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(this, dispenserBehavior); + } + + + public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) { + + if (!world.isRemote && Predicates.MAGI.test(player)) { + pos = pos.offset(side); + + double diffX = player.posX - (pos.getX() + 0.5); + double diffZ = player.posZ - (pos.getZ() + 0.5); + float yaw = (float)Math.toDegrees(Math.atan2(diffZ, diffX) + Math.PI); + + placeBook(world, pos.getX(), pos.getY(), pos.getZ(), yaw); + + if (!player.capabilities.isCreativeMode) { + player.getHeldItem(hand).shrink(1); + } + + return EnumActionResult.SUCCESS; + } + return EnumActionResult.PASS; + } + + private static void placeBook(World world, int x, int y, int z, float yaw) { + EntitySpellbook book = new EntitySpellbook(world); + + book.setPositionAndRotation(x + 0.5, y, z + 0.5, yaw, 0); + book.renderYawOffset = 0; + book.prevRotationYaw = yaw; + + world.spawnEntity(book); + } +} + + + + + + + + + + + + + + + diff --git a/src/main/java/com/minelittlepony/unicopia/model/ModelSpellbook.java b/src/main/java/com/minelittlepony/unicopia/model/ModelSpellbook.java new file mode 100644 index 00000000..b6e0a442 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/model/ModelSpellbook.java @@ -0,0 +1,13 @@ +package com.minelittlepony.unicopia.model; + +import net.minecraft.client.model.ModelBook; +import net.minecraft.client.model.ModelRenderer; + +public class ModelSpellbook extends ModelBook { + public ModelSpellbook() { + super(); + bookSpine = (new ModelRenderer(this)).setTextureOffset(12, 0); + bookSpine.addBox(-1, -5, 0, 2, 10, 0, 0.1f); + bookSpine.rotateAngleY = ((float)Math.PI / 2F); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/render/RenderSpellbook.java b/src/main/java/com/minelittlepony/unicopia/render/RenderSpellbook.java new file mode 100644 index 00000000..eb8eed36 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/render/RenderSpellbook.java @@ -0,0 +1,73 @@ +package com.minelittlepony.unicopia.render; + +import com.minelittlepony.unicopia.entity.EntitySpellbook; +import com.minelittlepony.unicopia.model.ModelSpellbook; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderLiving; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.ResourceLocation; + +public class RenderSpellbook extends RenderLiving { + + private static final ResourceLocation texture = new ResourceLocation("textures/entity/enchanting_table_book.png"); + + public RenderSpellbook(RenderManager rendermanagerIn) { + super(rendermanagerIn, new ModelSpellbook(), 0); + } + + @Override + protected ResourceLocation getEntityTexture(EntitySpellbook entity) { + return texture; + } + + @Override + protected float getDeathMaxRotation(EntitySpellbook entity) { + return 0; + } + + @Override + protected void renderModel(EntitySpellbook entity, float time, float walkSpeed, float stutter, float yaw, float pitch, float increment) { + + float breath = MathHelper.sin(((float)entity.ticksExisted + stutter) / 20) * 0.01F + 0.1F; + + float first_page_rot = walkSpeed + (breath * 10); + float second_page_rot = 1 - first_page_rot; + float open_angle = 0.9f - walkSpeed; + + if (first_page_rot > 1) first_page_rot = 1; + if (second_page_rot > 1) second_page_rot = 1; + + if (!((EntitySpellbook)entity).getIsOpen()) { + GlStateManager.translate(0, 1.44f, 0); + } else { + GlStateManager.translate(0, 1.2f + breath, 0); + } + GlStateManager.pushMatrix(); + + if (!((EntitySpellbook)entity).getIsOpen()) { + first_page_rot = second_page_rot = open_angle = 0; + GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(90.0F, 0.0F, 0.0F, 1.0F); + GlStateManager.translate(-0.25f, 0, 0); + } else { + GlStateManager.rotate(-60.0F, 0.0F, 0.0F, 1.0F); + } + + GlStateManager.enableCull(); + super.renderModel(entity, 0, first_page_rot, second_page_rot, open_angle, 0.0F, 0.0625F); + + GlStateManager.popMatrix(); + } + + @Override + protected void applyRotations(EntitySpellbook entity, float p_77043_2_, float p_77043_3_, float partialTicks) { + GlStateManager.rotate(-interpolateRotation(entity.prevRotationYaw, entity.rotationYaw, partialTicks), 0, 1, 0); + } + + @Override + protected boolean canRenderName(EntitySpellbook targetEntity) { + return super.canRenderName(targetEntity) && (targetEntity.getAlwaysRenderNameTagForRender() || targetEntity.hasCustomName() && targetEntity == renderManager.pointedEntity); + } +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index ac6986ee..c303410c 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -64,7 +64,7 @@ entity.racing_cloud.name=Bucking Bronco entity.construction_cloud.name=Construction Cloud entity.cloud.name=Cloud entity.spell.name=Magic - +entity.spellbook.name=Spellbook commands.race.success.self=Your race has been updated commands.race.success.otherself=%s changed race to %s diff --git a/src/main/resources/assets/unicopia/models/item/spellbook.json b/src/main/resources/assets/unicopia/models/item/spellbook.json new file mode 100644 index 00000000..82e46601 --- /dev/null +++ b/src/main/resources/assets/unicopia/models/item/spellbook.json @@ -0,0 +1,18 @@ +{ + "parent": "builtin/generated", + "textures": { + "layer0": "unicopia:items/spellbook" + }, + "display": { + "thirdperson": { + "rotation": [ -90, 0, 0 ], + "translation": [ 0, 1, -3 ], + "scale": [ 0.55, 0.55, 0.55 ] + }, + "firstperson": { + "rotation": [ 0, -135, 25 ], + "translation": [ 0, 4, 2 ], + "scale": [ 1.7, 1.7, 1.7 ] + } + } +} diff --git a/src/main/resources/assets/unicopia/recipes/spellbook.json b/src/main/resources/assets/unicopia/recipes/spellbook.json new file mode 100644 index 00000000..19fab215 --- /dev/null +++ b/src/main/resources/assets/unicopia/recipes/spellbook.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "minecraft:book", + "data": 0 + }, + { + "item": "unicopia:gem", + "data": 0 + } + ], + "result": { + "item": "unicopia:spellbook", + "count": 1, + "data": 0 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/unicopia/textures/items/spellbook.png b/src/main/resources/assets/unicopia/textures/items/spellbook.png new file mode 100644 index 00000000..992380b0 Binary files /dev/null and b/src/main/resources/assets/unicopia/textures/items/spellbook.png differ