Merge branch '4.3-dev' into 1.12.2
This commit is contained in:
@@ -2,9 +2,14 @@ package electroblob.wizardry.client;
|
||||
|
||||
import electroblob.wizardry.CommonProxy;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockBookshelf;
|
||||
import electroblob.wizardry.client.animation.ActionAnimation;
|
||||
import electroblob.wizardry.client.animation.PlayerAnimator;
|
||||
import electroblob.wizardry.client.audio.MovingSoundEntity;
|
||||
import electroblob.wizardry.client.audio.MovingSoundSpellCharge;
|
||||
import electroblob.wizardry.client.audio.SoundLoop;
|
||||
import electroblob.wizardry.client.audio.SoundLoopSpell;
|
||||
import electroblob.wizardry.client.gui.GuiLectern;
|
||||
import electroblob.wizardry.client.gui.GuiSpellDisplay;
|
||||
import electroblob.wizardry.client.gui.config.NamedBooleanEntry;
|
||||
import electroblob.wizardry.client.gui.config.SpellHUDSkinChooserEntry;
|
||||
@@ -12,8 +17,12 @@ import electroblob.wizardry.client.gui.handbook.GuiWizardHandbook;
|
||||
import electroblob.wizardry.client.model.ModelWizardArmour;
|
||||
import electroblob.wizardry.client.particle.*;
|
||||
import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory;
|
||||
import electroblob.wizardry.client.renderer.*;
|
||||
import electroblob.wizardry.client.renderer.entity.*;
|
||||
import electroblob.wizardry.client.renderer.entity.layers.*;
|
||||
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
|
||||
import electroblob.wizardry.client.renderer.tileentity.*;
|
||||
import electroblob.wizardry.command.SpellEmitter;
|
||||
import electroblob.wizardry.constants.Constants;
|
||||
import electroblob.wizardry.data.DispenserCastingData;
|
||||
import electroblob.wizardry.data.SpellEmitterData;
|
||||
import electroblob.wizardry.data.SpellGlyphData;
|
||||
@@ -32,10 +41,7 @@ import electroblob.wizardry.packet.*;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.*;
|
||||
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
|
||||
import electroblob.wizardry.tileentity.TileEntityMagicLight;
|
||||
import electroblob.wizardry.tileentity.TileEntityShrineCore;
|
||||
import electroblob.wizardry.tileentity.TileEntityStatue;
|
||||
import electroblob.wizardry.tileentity.*;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import electroblob.wizardry.util.WandHelper;
|
||||
@@ -72,6 +78,8 @@ import net.minecraft.util.text.Style;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraft.village.MerchantRecipeList;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.settings.KeyConflictContext;
|
||||
import net.minecraftforge.client.settings.KeyModifier;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.config.Property;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.NumberSliderEntry;
|
||||
@@ -79,6 +87,7 @@ import net.minecraftforge.fml.client.registry.ClientRegistry;
|
||||
import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -100,8 +109,16 @@ public class ClientProxy extends CommonProxy {
|
||||
private static final Map<ResourceLocation, IWizardryParticleFactory> factories = new HashMap<>();
|
||||
|
||||
// Key Bindings
|
||||
public static final KeyBinding NEXT_SPELL = new KeyBinding("key." + Wizardry.MODID + ".next_spell", Keyboard.KEY_N, "key.categories." + Wizardry.MODID);
|
||||
public static final KeyBinding PREVIOUS_SPELL = new KeyBinding("key." + Wizardry.MODID + ".previous_spell", Keyboard.KEY_B, "key.categories." + Wizardry.MODID);
|
||||
public static final KeyBinding NEXT_SPELL = new KeyBinding("key." + Wizardry.MODID + ".next_spell", KeyConflictContext.IN_GAME, Keyboard.KEY_N, "key.categories." + Wizardry.MODID);
|
||||
public static final KeyBinding PREVIOUS_SPELL = new KeyBinding("key." + Wizardry.MODID + ".previous_spell", KeyConflictContext.IN_GAME, Keyboard.KEY_B, "key.categories." + Wizardry.MODID);
|
||||
public static final KeyBinding[] SPELL_QUICK_ACCESS = new KeyBinding[ItemWand.BASE_SPELL_SLOTS + Constants.UPGRADE_STACK_LIMIT];
|
||||
|
||||
static {
|
||||
for(int i = 0; i < SPELL_QUICK_ACCESS.length; i++){
|
||||
SPELL_QUICK_ACCESS[i] = new KeyBinding("key." + Wizardry.MODID + ".spell_" + (i+1),
|
||||
KeyConflictContext.IN_GAME, KeyModifier.ALT, Keyboard.KEY_1 + i, "key.categories." + Wizardry.MODID);
|
||||
}
|
||||
}
|
||||
|
||||
// Armour Model
|
||||
public static final ModelBiped WIZARD_ARMOUR_MODEL = new ModelWizardArmour(0.75f);
|
||||
@@ -109,7 +126,7 @@ public class ClientProxy extends CommonProxy {
|
||||
/** The wrap width for standard multi-line descriptions (see {@link ClientProxy#addMultiLineDescription(List, String, Style, Object...)}). */
|
||||
private static final int TOOLTIP_WRAP_WIDTH = 140;
|
||||
|
||||
// SECTION Registry
|
||||
// Registry
|
||||
// ===============================================================================================================
|
||||
|
||||
@Override
|
||||
@@ -121,6 +138,7 @@ public class ClientProxy extends CommonProxy {
|
||||
public void registerKeyBindings(){
|
||||
ClientRegistry.registerKeyBinding(NEXT_SPELL);
|
||||
ClientRegistry.registerKeyBinding(PREVIOUS_SPELL);
|
||||
for(KeyBinding key : SPELL_QUICK_ACCESS) ClientRegistry.registerKeyBinding(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,7 +146,7 @@ public class ClientProxy extends CommonProxy {
|
||||
mixedFontRenderer = new MixedFontRenderer(Minecraft.getMinecraft().gameSettings, new ResourceLocation("textures/font/ascii.png"),
|
||||
Minecraft.getMinecraft().renderEngine, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerResourceReloadListeners(){
|
||||
IResourceManager manager = Minecraft.getMinecraft().getResourceManager();
|
||||
@@ -147,14 +165,14 @@ public class ClientProxy extends CommonProxy {
|
||||
WizardryAntiqueAtlasIntegration.registerMarkers();
|
||||
}
|
||||
|
||||
// SECTION Misc
|
||||
// Misc
|
||||
// ===============================================================================================================
|
||||
|
||||
@Override
|
||||
public void setToNumberSliderEntry(Property property){
|
||||
property.setConfigEntryClass(NumberSliderEntry.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setToHUDChooserEntry(Property property){
|
||||
property.setConfigEntryClass(SpellHUDSkinChooserEntry.class);
|
||||
@@ -171,32 +189,23 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playMovingSound(Entity entity, SoundEvent sound, SoundCategory category, float volume, float pitch, boolean repeat){
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(new MovingSoundEntity<>(entity, sound, category, volume, pitch, repeat));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSpellSoundLoop(EntityLivingBase entity, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch){
|
||||
SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellEntity(start, loop, end, spell, entity, volume, pitch));
|
||||
public EntityPlayer getThePlayer(){
|
||||
return Minecraft.getMinecraft().player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSpellSoundLoop(World world, double x, double y, double z, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch, int duration){
|
||||
if(duration == -1){
|
||||
SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellDispenser(start, loop, end, spell, world, x, y, z, volume, pitch));
|
||||
}else{
|
||||
SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellPosTimed(start, loop, end, spell, duration, x, y, z, volume, pitch));
|
||||
}
|
||||
public boolean isFirstPerson(Entity entity){
|
||||
return entity == Minecraft.getMinecraft().getRenderViewEntity() && Minecraft.getMinecraft().gameSettings.thirdPersonView == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playBlinkEffect(EntityPlayer player){
|
||||
if(Minecraft.getMinecraft().player == player) WizardryClientEventHandler.playBlinkEffect();
|
||||
if(Minecraft.getMinecraft().player == player) RenderBlinkEffect.playBlinkEffect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shakeScreen(EntityPlayer player, float intensity){
|
||||
if(Minecraft.getMinecraft().player == player) WizardryClientEventHandler.shakeScreen(intensity);
|
||||
if(Minecraft.getMinecraft().player == player) ScreenShakeHandler.shakeScreen(intensity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,17 +220,61 @@ public class ClientProxy extends CommonProxy {
|
||||
return GuiSpellDisplay.getSkinKeys();
|
||||
}
|
||||
|
||||
// SECTION Items
|
||||
@Override
|
||||
public void notifyBookshelfChange(World world, BlockPos pos){
|
||||
|
||||
super.notifyBookshelfChange(world, pos);
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
|
||||
if(player.getDistanceSq(pos) < BlockBookshelf.PLAYER_NOTIFY_RANGE * BlockBookshelf.PLAYER_NOTIFY_RANGE){
|
||||
if(Minecraft.getMinecraft().currentScreen instanceof GuiLectern){
|
||||
((GuiLectern)Minecraft.getMinecraft().currentScreen).refreshAvailableSpells();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sound
|
||||
// ===============================================================================================================
|
||||
|
||||
@Override
|
||||
public boolean shouldDisplayDiscovered(Spell spell, ItemStack stack){
|
||||
public void playMovingSound(Entity entity, SoundEvent sound, SoundCategory category, float volume, float pitch, boolean repeat){
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(new MovingSoundEntity<>(entity, sound, category, volume, pitch, repeat));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playChargeupSound(EntityLivingBase entity){
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(new MovingSoundSpellCharge(entity, WizardrySounds.ITEM_WAND_CHARGEUP, WizardrySounds.SPELLS, 2.5f, 1.4f, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSpellSoundLoop(EntityLivingBase entity, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch){
|
||||
SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellEntity(start, loop, end, spell, entity, volume, pitch));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSpellSoundLoop(World world, double x, double y, double z, Spell spell, SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, float pitch, int duration){
|
||||
if(duration == -1){
|
||||
SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellDispenser(start, loop, end, spell, world, x, y, z, volume, pitch));
|
||||
}else{
|
||||
SoundLoop.addLoop(new SoundLoopSpell.SoundLoopSpellPosTimed(start, loop, end, spell, duration, x, y, z, volume, pitch));
|
||||
}
|
||||
}
|
||||
|
||||
// Items
|
||||
// ===============================================================================================================
|
||||
|
||||
@Override
|
||||
public boolean shouldDisplayDiscovered(Spell spell, @Nullable ItemStack stack){
|
||||
|
||||
EntityPlayerSP player = Minecraft.getMinecraft().player;
|
||||
|
||||
if(player == null) return false;
|
||||
|
||||
// Displayed recipe
|
||||
// Weirdly, the gui is actually the only way of accessing the current IMerchant or their recipes, other than a
|
||||
// brute-force search through all the entities in the world to find the merchant interacting with the player
|
||||
// Since we only need this client-side anyway, we might as well go via the gui
|
||||
if(Minecraft.getMinecraft().currentScreen instanceof GuiMerchant){
|
||||
// It doesn't actually matter if the recipe is selected or not, since the itemstack will only ever
|
||||
// match one of them anyway - and we'd have to reflect into GuiMerchant to get the selected recipe
|
||||
@@ -298,12 +351,16 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMultiLineDescription(List<String> tooltip, String key, Style style, Object... args){
|
||||
String description = style.getFormattingCode() + I18n.format(key, args);
|
||||
tooltip.addAll(Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(description, TOOLTIP_WRAP_WIDTH));
|
||||
public String translate(String key, Style style, Object... args){
|
||||
return style.getFormattingCode() + I18n.format(key, args);
|
||||
}
|
||||
|
||||
// SECTION Particles
|
||||
@Override
|
||||
public void addMultiLineDescription(List<String> tooltip, String key, Style style, Object... args){
|
||||
tooltip.addAll(Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(translate(key, style, args), TOOLTIP_WRAP_WIDTH));
|
||||
}
|
||||
|
||||
// Particles
|
||||
// ===============================================================================================================
|
||||
|
||||
/** Use {@link ParticleWizardry#registerParticle(ResourceLocation, IWizardryParticleFactory)}, this is internal. */
|
||||
@@ -316,10 +373,13 @@ public class ClientProxy extends CommonProxy {
|
||||
public void registerParticles(){
|
||||
// I'll be a good programmer and use the API method rather than the one above. Lead by example, as they say...
|
||||
ParticleWizardry.registerParticle(Type.BEAM, ParticleBeam::new);
|
||||
ParticleWizardry.registerParticle(Type.BLOCK_HIGHLIGHT, ParticleBlockHighlight::new);
|
||||
ParticleWizardry.registerParticle(Type.BUFF, ParticleBuff::new);
|
||||
ParticleWizardry.registerParticle(Type.CLOUD, ParticleCloud::new);
|
||||
ParticleWizardry.registerParticle(Type.DARK_MAGIC, ParticleDarkMagic::new);
|
||||
ParticleWizardry.registerParticle(Type.DUST, ParticleDust::new);
|
||||
ParticleWizardry.registerParticle(Type.FLASH, ParticleFlash::new);
|
||||
ParticleWizardry.registerParticle(Type.GUARDIAN_BEAM, ParticleGuardianBeam::new);
|
||||
ParticleWizardry.registerParticle(Type.ICE, ParticleIce::new);
|
||||
ParticleWizardry.registerParticle(Type.LEAF, ParticleLeaf::new);
|
||||
ParticleWizardry.registerParticle(Type.LIGHTNING, ParticleLightning::new);
|
||||
@@ -332,10 +392,9 @@ public class ClientProxy extends CommonProxy {
|
||||
ParticleWizardry.registerParticle(Type.SPARK, ParticleSpark::new);
|
||||
ParticleWizardry.registerParticle(Type.SPARKLE, ParticleSparkle::new);
|
||||
ParticleWizardry.registerParticle(Type.SPHERE, ParticleSphere::new);
|
||||
ParticleWizardry.registerParticle(Type.SUMMON, ParticleSummon::new);
|
||||
ParticleWizardry.registerParticle(Type.VINE, ParticleVine::new);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ParticleWizardry createParticle(ResourceLocation type, World world, double x, double y, double z){
|
||||
IWizardryParticleFactory factory = factories.get(type);
|
||||
@@ -352,7 +411,7 @@ public class ClientProxy extends CommonProxy {
|
||||
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleTornado(world, maxAge, x, z, radius, y, velX, velZ, block).setBlockPos(pos));// , world.rand.nextInt(6)));
|
||||
}
|
||||
|
||||
// SECTION Packet Handlers
|
||||
// Packet Handlers
|
||||
// ===============================================================================================================
|
||||
|
||||
@Override
|
||||
@@ -455,72 +514,74 @@ public class ClientProxy extends CommonProxy {
|
||||
Wizardry.logger.warn("Recieved a PacketNPCCastSpell, but the caster ID was not the ID of an EntityLiving");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handleDispenserCastSpellPacket(PacketDispenserCastSpell.Message message){
|
||||
|
||||
|
||||
World world = Minecraft.getMinecraft().world;
|
||||
|
||||
|
||||
if(world.getTileEntity(message.pos) instanceof TileEntityDispenser){ // Should always be true
|
||||
|
||||
|
||||
Spell spell = Spell.byNetworkID(message.spellID);
|
||||
|
||||
|
||||
spell.cast(world, message.x, message.y, message.z, message.direction, 0, -1, message.modifiers);
|
||||
// No need to check if the spell succeeded, because the packet is only ever sent when it succeeds.
|
||||
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.DISPENSER, spell, world, message.x, message.y,
|
||||
message.z, message.direction, message.modifiers));
|
||||
|
||||
|
||||
if(spell.isContinuous || spell instanceof None){
|
||||
|
||||
|
||||
DispenserCastingData data = DispenserCastingData.get((TileEntityDispenser)world.getTileEntity(message.pos));
|
||||
|
||||
|
||||
if(spell.isContinuous){
|
||||
data.startCasting(spell, message.x, message.y, message.z, message.duration, message.modifiers);
|
||||
}else{
|
||||
data.stopCasting();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
Wizardry.logger.warn("Recieved a PacketDispenserCastSpell, but no tileEntity was found at the supplied location.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTransportationPacket(PacketTransportation.Message message){
|
||||
|
||||
World world = Minecraft.getMinecraft().world;
|
||||
Entity caster = world.getEntityByID(message.casterID);
|
||||
BlockPos pos = message.destination;
|
||||
|
||||
if(caster == null) return; // Shouldn't happen
|
||||
Entity entity = world.getEntityByID(message.dismountEntityID);
|
||||
if(message.dismountEntityID != -1 && entity != null) entity.dismountRidingEntity();
|
||||
|
||||
// Moved from when the packet is sent to when it is received; fixes the sound not playing in first person.
|
||||
caster.playSound(WizardrySounds.SPELL_TRANSPORTATION_TRAVEL, 1, 1);
|
||||
// Changed to a position to avoid syncing issues
|
||||
world.playSound(pos.getX(), pos.getY(), pos.getZ(), WizardrySounds.SPELL_TRANSPORTATION_TRAVEL, WizardrySounds.SPELLS, 1, 1, false);
|
||||
|
||||
for(int i = 0; i < 20; i++){
|
||||
double radius = 1;
|
||||
float angle = world.rand.nextFloat() * (float)Math.PI * 2;
|
||||
double x = caster.posX + radius * MathHelper.cos(angle);
|
||||
double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2;
|
||||
double z = caster.posZ + radius * MathHelper.sin(angle);
|
||||
double x = pos.getX() + 0.5 + radius * MathHelper.cos(angle);
|
||||
double y = pos.getY() + world.rand.nextDouble() * 2;
|
||||
double z = pos.getZ() + 0.5 + radius * MathHelper.sin(angle);
|
||||
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.02, 0).clr(0.6f, 1, 0.6f)
|
||||
.time(80 + world.rand.nextInt(10)).spawn(world);
|
||||
}
|
||||
for(int i = 0; i < 20; i++){
|
||||
double radius = 1;
|
||||
float angle = world.rand.nextFloat() * (float)Math.PI * 2;
|
||||
double x = caster.posX + radius * MathHelper.cos(angle);
|
||||
double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2;
|
||||
double z = caster.posZ + radius * MathHelper.sin(angle);
|
||||
double x = pos.getX() + 0.5 + radius * MathHelper.cos(angle);
|
||||
double y = pos.getY() + world.rand.nextDouble() * 2;
|
||||
double z = pos.getZ() + 0.5 + radius * MathHelper.sin(angle);
|
||||
world.spawnParticle(EnumParticleTypes.VILLAGER_HAPPY, x, y, z, 0, 0.02, 0);
|
||||
}
|
||||
for(int i = 0; i < 20; i++){
|
||||
double radius = 1;
|
||||
float angle = world.rand.nextFloat() * (float)Math.PI * 2;
|
||||
double x = caster.posX + radius * MathHelper.cos(angle);
|
||||
double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2;
|
||||
double z = caster.posZ + radius * MathHelper.sin(angle);
|
||||
double x = pos.getX() + 0.5 + radius * MathHelper.cos(angle);
|
||||
double y = pos.getY() + world.rand.nextDouble() * 2;
|
||||
double z = pos.getZ() + 0.5 + radius * MathHelper.sin(angle);
|
||||
world.spawnParticle(EnumParticleTypes.ENCHANTMENT_TABLE, x, y, z, 0, 0.02, 0);
|
||||
}
|
||||
}
|
||||
@@ -639,7 +700,7 @@ public class ClientProxy extends CommonProxy {
|
||||
}else Wizardry.logger.warn("Received a PacketConquerShrine, but there was no shrine core at the position sent");
|
||||
}
|
||||
|
||||
// SECTION Rendering
|
||||
// Rendering
|
||||
// ===============================================================================================================
|
||||
|
||||
private static final ResourceLocation ICE_WRAITH_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/ice_wraith.png");
|
||||
@@ -650,8 +711,17 @@ public class ClientProxy extends CommonProxy {
|
||||
|
||||
@Override
|
||||
public void initialiseLayers(){
|
||||
LayerStone.initialiseLayers();
|
||||
LayerFrost.initialiseLayers();
|
||||
LayerTiledOverlay.initialiseLayers(LayerStone::new);
|
||||
LayerTiledOverlay.initialiseLayers(LayerFrost::new);
|
||||
LayerTiledOverlay.initialiseLayers(LayerMindControl::new);
|
||||
LayerTiledOverlay.initialiseLayers(LayerSummonAnimation::new);
|
||||
LayerTiledOverlay.initialiseLayers(LayerDisintegrateAnimation::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialiseAnimations(){
|
||||
PlayerAnimator.init();
|
||||
ActionAnimation.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -695,7 +765,9 @@ public class ClientProxy extends CommonProxy {
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityDart.class, manager -> new RenderMagicArrow(manager,
|
||||
new ResourceLocation(Wizardry.MODID, "textures/entity/dart.png"), false, 8.0, 2.0, 16, 5, true));
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityIceLance.class, manager -> new RenderMagicArrow(manager,
|
||||
new ResourceLocation(Wizardry.MODID, "textures/entity/ice_lance.png"), false, 16.0, 3.0, 22, 5, true));
|
||||
new ResourceLocation(Wizardry.MODID, "textures/entity/ice_lance.png"), false, 16.0, 3.0, 22, 5, false));
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityFlamecatcherArrow.class, manager -> new RenderMagicArrow(manager,
|
||||
new ResourceLocation(Wizardry.MODID, "textures/entity/flamecatcher_arrow.png"), false, 8, 2.0, 16, 5, true));
|
||||
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityForceArrow.class, RenderForceArrow::new);
|
||||
|
||||
@@ -705,6 +777,7 @@ public class ClientProxy extends CommonProxy {
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityWizard.class, RenderWizard::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityEvilWizard.class, RenderEvilWizard::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityDecoy.class, RenderDecoy::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityRemnant.class, RenderRemnant::new);
|
||||
|
||||
// Throwables
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntitySparkBomb.class,
|
||||
@@ -743,6 +816,11 @@ public class ClientProxy extends CommonProxy {
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityHammer.class, RenderHammer::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityIceSpike.class, RenderIceSpike::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityForcefield.class, RenderForcefield::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityZombieSpawner.class, RenderZombieSpawner::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityRadiantTotem.class, RenderRadiantTotem::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityBoulder.class, RenderBoulder::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityWitheringTotem.class, RenderWitheringTotem::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityIceBarrier.class, RenderIceBarrier::new);
|
||||
//RenderingRegistry.registerEntityRenderingHandler(EntityContainmentField.class, RenderContainmentField::new);
|
||||
|
||||
// Stuff that doesn't render
|
||||
@@ -754,26 +832,29 @@ public class ClientProxy extends CommonProxy {
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityStormElemental.class, RenderBlank::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityEarthquake.class, RenderBlank::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityHailstorm.class, RenderBlank::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityStormcloud.class, RenderBlank::new);
|
||||
|
||||
// Runes on ground
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityHealAura.class,
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/healing_aura.png"), 5.0f, false));
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/healing_aura.png"), 0.3f, false));
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityFireSigil.class,
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/fire_sigil.png"), 2.0f, true));
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/fire_sigil.png"), 0, true));
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityFrostSigil.class,
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/frost_sigil.png"), 2.0f, true));
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/frost_sigil.png"), 0, true));
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityLightningSigil.class,
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_sigil.png"), 2.0f, true));
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_sigil.png"), 0, true));
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityFireRing.class,
|
||||
manager -> new RenderFireRing(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/ring_of_fire.png"), 5.0f));
|
||||
manager -> new RenderFireRing(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/ring_of_fire.png")));
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityDecay.class, RenderDecay::new);
|
||||
RenderingRegistry.registerEntityRenderingHandler(EntityCombustionRune.class,
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/combustion_rune.png"), 2.0f, true));
|
||||
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/combustion_rune.png"), 0, true));
|
||||
|
||||
// TESRs
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityArcaneWorkbench.class, new RenderArcaneWorkbench());
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityStatue.class, renderStatue = new RenderStatue());
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMagicLight.class, new RenderMagicLight());
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityLectern.class, new RenderLectern());
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityImbuementAltar.class, new RenderImbuementAltar());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,10 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Utility class containing some useful static methods for drawing GUIs. Previously these were spread across the main
|
||||
* {@code WizardryUtilities} class and various individual GUI classes.
|
||||
* Utility class containing some useful static methods for drawing GUIs, as well as general rendering.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.2
|
||||
@@ -124,6 +125,29 @@ public final class DrawingUtils {
|
||||
tessellator.draw();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a 'glitch' rectangle, with some rows of pixels shifted randomly to give a broken effect.
|
||||
*
|
||||
* @param random A random number generator to use
|
||||
* @param x The x position of the rectangle
|
||||
* @param y The y position of the rectangle
|
||||
* @param u The x position of the top left corner of the section of the image wanted
|
||||
* @param v The y position of the top left corner of the section of the image wanted
|
||||
* @param width The width of the section
|
||||
* @param height The height of the section
|
||||
* @param textureWidth The width of the actual image.
|
||||
* @param textureHeight The height of the actual image.
|
||||
* @param flipX Whether to flip the texture in the x direction.
|
||||
* @param flipY Whether to flip the texture in the y direction.
|
||||
*/
|
||||
public static void drawGlitchRect(Random random, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight, boolean flipX, boolean flipY){
|
||||
for(int i=0; i<height; i++){
|
||||
if(flipY) i = height - i - 1;
|
||||
int offset = random.nextInt(4) == 0 ? random.nextInt(6) - 3 : 0;
|
||||
drawTexturedFlippedRect(x + offset, y + i, u, v + i, width, 1, textureWidth, textureHeight, flipX, flipY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixes the two given opaque colours in the proportion specified.
|
||||
* @param colour1 The first colour to mix, as a 6-digit hexadecimal.
|
||||
@@ -156,7 +180,7 @@ public final class DrawingUtils {
|
||||
* @return The resulting integer colour code, which will be an 8-digit hexadecimal.
|
||||
*/
|
||||
public static int makeTranslucent(int colour, float opacity){
|
||||
return colour + ((int)(0xff * opacity * 0x01000000));
|
||||
return colour + ((int)(opacity * 0xff) << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,4 +268,37 @@ public final class DrawingUtils {
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a factor between 0 and 1 that results in a smooth, aesthetically-pleasing animation when used to scale
|
||||
* things. Mainly for rendering, but can be used anywhere since it's just a mathematical formula.
|
||||
* @param lifetime The lifetime of the thing being animated, in ticks (if this is negative, disappearing is ignored)
|
||||
* @param ticksExisted The current age of the thing being animated, in ticks
|
||||
* @param partialTicks The current partial tick time
|
||||
* @param startLength The length of the appearing animation, in ticks
|
||||
* @param endLength The length of the disappearing animation, in ticks
|
||||
* @return A fraction between 0 and 1, with the value at the very start and end being 0 and the constant middle
|
||||
* section having a value of 1.
|
||||
*/
|
||||
public static float smoothScaleFactor(int lifetime, int ticksExisted, float partialTicks, int startLength, int endLength){
|
||||
float age = ticksExisted + partialTicks;
|
||||
float s = MathHelper.clamp(age < startLength || lifetime < 0 ? age/startLength : (lifetime - age) / endLength, 0, 1);
|
||||
s = (float)Math.pow(s, 0.4); // Smooths the animation
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the point with the given coordinates lies within the rectangle specified. The check is identical to
|
||||
* {@link GuiContainer#isPointInRegion(int, int, int, int, int, int)}, but without the adjustment relative to the GUI.
|
||||
* @param left The minimum x coordinate of the rectangle
|
||||
* @param top The minimum y coordinate of the rectangle
|
||||
* @param width The width of the rectangle
|
||||
* @param height The height of the rectangle
|
||||
* @param x The x coordinate of the point to test
|
||||
* @param y The y coordinate of the point to test
|
||||
* @return True if the given point is in the rectangle, false otherwise
|
||||
*/
|
||||
public static boolean isPointInRegion(int left, int top, int width, int height, int x, int y){
|
||||
return x >= left - 1 && x < left + width + 1 && y >= top - 1 && y < top + height + 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package electroblob.wizardry.client;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class ScreenShakeHandler {
|
||||
|
||||
/** The remaining time for which the screen shake effect will be active. */
|
||||
private static int screenShakeCounter = 0;
|
||||
private static final float SHAKINESS = 0.5f;
|
||||
|
||||
/** Starts the client-side screen shake effect. */
|
||||
public static void shakeScreen(float intensity){
|
||||
if(Wizardry.settings.screenShake){
|
||||
screenShakeCounter = (int)(intensity / SHAKINESS);
|
||||
Minecraft.getMinecraft().player.rotationPitch -= intensity * 0.5f; // Start halfway down
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){
|
||||
|
||||
if(event.player == Minecraft.getMinecraft().player && event.phase == TickEvent.Phase.END){
|
||||
|
||||
if(Wizardry.settings.screenShake){
|
||||
if(screenShakeCounter > 0){
|
||||
float magnitude = screenShakeCounter * SHAKINESS;
|
||||
Minecraft.getMinecraft().player.rotationPitch += screenShakeCounter % 2 == 0 ? magnitude : -magnitude;
|
||||
screenShakeCounter--;
|
||||
}
|
||||
}else{
|
||||
screenShakeCounter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +1,35 @@
|
||||
package electroblob.wizardry.client;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockMagicLight;
|
||||
import electroblob.wizardry.constants.Constants;
|
||||
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
|
||||
import electroblob.wizardry.data.DispenserCastingData;
|
||||
import electroblob.wizardry.data.SpellEmitterData;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.item.ISpellCastingItem;
|
||||
import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.item.ItemFlamecatcher;
|
||||
import electroblob.wizardry.item.ItemSpectralBow;
|
||||
import electroblob.wizardry.item.ItemWand;
|
||||
import electroblob.wizardry.potion.PotionSlowTime;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.spell.*;
|
||||
import electroblob.wizardry.util.RayTracer;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.spell.Possession;
|
||||
import electroblob.wizardry.spell.SixthSense;
|
||||
import electroblob.wizardry.spell.SlowTime;
|
||||
import electroblob.wizardry.spell.Transience;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiMerchant;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.item.EntityArmorStand;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.village.MerchantRecipe;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.*;
|
||||
import net.minecraftforge.client.event.FOVUpdateEvent;
|
||||
import net.minecraftforge.client.event.InputUpdateEvent;
|
||||
import net.minecraftforge.client.event.MouseEvent;
|
||||
import net.minecraftforge.client.event.RenderHandEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
@@ -46,8 +40,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Event handler responsible for client-side only events, mostly rendering.
|
||||
*
|
||||
* General-purpose client-side event handler for things that don't fit anywhere else or groups of related behaviours
|
||||
* that are better kept together.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 1.0
|
||||
*/
|
||||
@@ -55,67 +50,19 @@ import java.util.List;
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public final class WizardryClientEventHandler {
|
||||
|
||||
private static final ResourceLocation sixthSenseTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/sixth_sense.png");
|
||||
private static final ResourceLocation sixthSenseOverlayTexture = new ResourceLocation(Wizardry.MODID, "textures/gui/sixth_sense_overlay.png");
|
||||
private static final ResourceLocation frostOverlayTexture = new ResourceLocation(Wizardry.MODID, "textures/gui/frost_overlay.png");
|
||||
private static final ResourceLocation blinkOverlayTexture = new ResourceLocation(Wizardry.MODID, "textures/gui/blink_overlay.png");
|
||||
private static final ResourceLocation pointerTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/pointer.png");
|
||||
private static final ResourceLocation targetPointerTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/target_pointer.png");
|
||||
private WizardryClientEventHandler(){} // No instances!
|
||||
|
||||
/** The remaining time for which the blink screen overlay effect will be displayed in first-person. Since this is
|
||||
* only for the first-person player (the instance of which is itself stored in a static variable), this can simply
|
||||
* be stored statically here, rather than needing to be in {@code WizardData}. */
|
||||
private static int blinkEffectTimer;
|
||||
/** The number of ticks the blink effect lasts for. */
|
||||
private static final int BLINK_EFFECT_DURATION = 8;
|
||||
// Tick Events
|
||||
// ===============================================================================================================
|
||||
|
||||
/** The remaining time for which the screen shake effect will be active. */
|
||||
private static int screenShakeCounter = 0;
|
||||
private static final float SHAKINESS = 0.5f;
|
||||
|
||||
/** Starts the first-person blink overlay effect. */
|
||||
public static void playBlinkEffect(){
|
||||
if(Wizardry.settings.blinkEffect) blinkEffectTimer = BLINK_EFFECT_DURATION;
|
||||
}
|
||||
|
||||
/** Starts the client-side screen shake effect. */
|
||||
public static void shakeScreen(float intensity){
|
||||
if(Wizardry.settings.screenShake){
|
||||
screenShakeCounter = (int)(intensity / SHAKINESS);
|
||||
Minecraft.getMinecraft().player.rotationPitch -= intensity * 0.5f; // Start halfway down
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){
|
||||
|
||||
if(event.player == Minecraft.getMinecraft().player && event.phase == TickEvent.Phase.END){
|
||||
|
||||
if(Wizardry.settings.blinkEffect){
|
||||
if(blinkEffectTimer > 0) blinkEffectTimer--;
|
||||
}else{
|
||||
blinkEffectTimer = 0;
|
||||
}
|
||||
|
||||
if(Wizardry.settings.screenShake){
|
||||
if(screenShakeCounter > 0){
|
||||
float magnitude = screenShakeCounter * SHAKINESS;
|
||||
Minecraft.getMinecraft().player.rotationPitch += screenShakeCounter % 2 == 0 ? magnitude : -magnitude;
|
||||
screenShakeCounter--;
|
||||
}
|
||||
}else{
|
||||
screenShakeCounter = 0;
|
||||
}
|
||||
|
||||
// Only seems to work here...
|
||||
// EntityLiving victim = Possession.getPossessee(Minecraft.getMinecraft().player);
|
||||
// if(victim != null && victim.getHeldItemMainhand().isEmpty()){
|
||||
// Minecraft.getMinecraft().player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY);
|
||||
// }
|
||||
|
||||
// Reset shaders if their respective potions aren't active
|
||||
// This is a player so the potion effects are synced by vanilla
|
||||
if(Minecraft.getMinecraft().entityRenderer.getShaderGroup() != null){
|
||||
if(Minecraft.getMinecraft().entityRenderer.getShaderGroup() != null){ // IntelliJ is wrong, this can be null
|
||||
|
||||
String activeShader = Minecraft.getMinecraft().entityRenderer.getShaderGroup().getShaderGroupName();
|
||||
|
||||
@@ -124,41 +71,16 @@ public final class WizardryClientEventHandler {
|
||||
|| (activeShader.equals(Transience.SHADER.toString()) && !Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.transience))){
|
||||
|
||||
if(activeShader.equals(SixthSense.SHADER.toString())
|
||||
|| activeShader.equals(Transience.SHADER.toString())) playBlinkEffect();
|
||||
|| activeShader.equals(Transience.SHADER.toString())) RenderBlinkEffect.playBlinkEffect();
|
||||
|
||||
Minecraft.getMinecraft().entityRenderer.stopUseShader();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderHandEvent(RenderHandEvent event){
|
||||
|
||||
EntityLiving victim = Possession.getPossessee(Minecraft.getMinecraft().player);
|
||||
|
||||
if(victim != null){
|
||||
|
||||
victim.rotationYawHead = Minecraft.getMinecraft().player.rotationYaw;
|
||||
|
||||
if(Minecraft.getMinecraft().player.getHeldItemMainhand().isEmpty()){
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This event is called every tick, not just when a movement key is pressed
|
||||
@SubscribeEvent
|
||||
public static void onInputUpdateEvent(InputUpdateEvent event){
|
||||
// Prevents the player moving when paralysed
|
||||
if(event.getEntityPlayer().isPotionActive(WizardryPotions.paralysis)){
|
||||
event.getMovementInput().moveForward = 0;
|
||||
event.getMovementInput().moveStrafe = 0;
|
||||
event.getMovementInput().jump = false;
|
||||
event.getMovementInput().sneak = false;
|
||||
}
|
||||
}
|
||||
|
||||
// The classes referenced here used to handle their own client tick events, but since they're not client-only
|
||||
// classes, that crashed the dedicated server...
|
||||
@SubscribeEvent
|
||||
public static void onClientTickEvent(TickEvent.ClientTickEvent event){
|
||||
|
||||
@@ -183,10 +105,13 @@ public final class WizardryClientEventHandler {
|
||||
PotionSlowTime.cleanUpEntities(world);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Input and Controls
|
||||
// ===============================================================================================================
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onMouseEvent(MouseEvent event){
|
||||
|
||||
|
||||
// Prevents the player looking around when paralysed
|
||||
if(Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.paralysis)
|
||||
&& Minecraft.getMinecraft().inGameHasFocus){
|
||||
@@ -198,267 +123,76 @@ public final class WizardryClientEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// This event is called every tick, not just when a movement key is pressed
|
||||
@SubscribeEvent
|
||||
public static void onFOVUpdateEvent(FOVUpdateEvent event){
|
||||
|
||||
// Bow zoom. Taken directly from AbstractClientPlayer so it works exactly like vanilla.
|
||||
if(event.getEntity().isHandActive() && event.getEntity().getActiveItemStack().getItem() instanceof ItemSpectralBow){
|
||||
|
||||
int maxUseTicks = event.getEntity().getItemInUseMaxCount();
|
||||
|
||||
float maxUseSeconds = (float)maxUseTicks / 20.0F;
|
||||
|
||||
if(maxUseSeconds > 1.0F){
|
||||
maxUseSeconds = 1.0F;
|
||||
}else{
|
||||
maxUseSeconds = maxUseSeconds * maxUseSeconds;
|
||||
}
|
||||
|
||||
event.setNewfov(event.getFov() * 1.0F - maxUseSeconds * 0.15F);
|
||||
public static void onInputUpdateEvent(InputUpdateEvent event){
|
||||
// Prevents the player moving when paralysed
|
||||
if(event.getEntityPlayer().isPotionActive(WizardryPotions.paralysis)){
|
||||
event.getMovementInput().moveForward = 0;
|
||||
event.getMovementInput().moveStrafe = 0;
|
||||
event.getMovementInput().jump = false;
|
||||
event.getMovementInput().sneak = false;
|
||||
}
|
||||
|
||||
if(blinkEffectTimer > 0){
|
||||
float f = ((float)Math.max(blinkEffectTimer - 2, 0))/BLINK_EFFECT_DURATION;
|
||||
event.setNewfov(event.getFov() + f * f * 0.7f);
|
||||
|
||||
if(ItemArtefact.isArtefactActive(event.getEntityPlayer(), WizardryItems.charm_move_speed)
|
||||
&& event.getEntityPlayer().isHandActive()
|
||||
&& event.getEntityPlayer().getActiveItemStack().getItem() instanceof ItemWand){
|
||||
// Normally speed is set to 20% when using items, this makes it 80%
|
||||
event.getMovementInput().moveStrafe *= 4;
|
||||
event.getMovementInput().moveForward *= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering
|
||||
// ===============================================================================================================
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onDrawBlockHighlightEvent(DrawBlockHighlightEvent event){
|
||||
// Hide the block outline for magic light blocks unless the player can dispel them
|
||||
if(event.getTarget().typeOfHit == RayTraceResult.Type.BLOCK
|
||||
&& event.getPlayer().world.getBlockState(event.getTarget().getBlockPos()).getBlock() instanceof BlockMagicLight){
|
||||
public static void onRenderHandEvent(RenderHandEvent event){
|
||||
|
||||
if((!(event.getPlayer().getHeldItemMainhand().getItem() instanceof ISpellCastingItem)
|
||||
&& !(event.getPlayer().getHeldItemOffhand().getItem() instanceof ISpellCastingItem))
|
||||
|| !ItemArtefact.isArtefactActive(event.getPlayer(), WizardryItems.charm_light)){
|
||||
// Hide the player's empty hand in first-person when possessing
|
||||
EntityLiving victim = Possession.getPossessee(Minecraft.getMinecraft().player);
|
||||
|
||||
if(victim != null){
|
||||
|
||||
victim.rotationYawHead = Minecraft.getMinecraft().player.rotationYaw;
|
||||
|
||||
if(Minecraft.getMinecraft().player.getHeldItemMainhand().isEmpty()){
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Brute-force fix for crystals not showing up when a wizard is given a spell book in the trade GUI.
|
||||
@SubscribeEvent
|
||||
public static void onGuiDrawForegroundEvent(GuiContainerEvent.DrawForeground event){
|
||||
public static void onFOVUpdateEvent(FOVUpdateEvent event){
|
||||
|
||||
if(event.getGuiContainer() instanceof GuiMerchant){
|
||||
|
||||
GuiMerchant gui = (GuiMerchant)event.getGuiContainer();
|
||||
// Note that gui.getMerchant() returns an NpcMerchant, not an EntityWizard.
|
||||
|
||||
// Using == the specific item rather than instanceof because that's how trades do it.
|
||||
if(gui.inventorySlots.getSlot(0).getStack().getItem() == WizardryItems.spell_book
|
||||
|| gui.inventorySlots.getSlot(1).getStack().getItem() == WizardryItems.spell_book){
|
||||
|
||||
for(MerchantRecipe trade : gui.getMerchant().getRecipes(Minecraft.getMinecraft().player)){
|
||||
if(trade.getItemToBuy().getItem() == WizardryItems.spell_book && trade.getSecondItemToBuy().isEmpty()){
|
||||
Slot slot = gui.inventorySlots.getSlot(2);
|
||||
// It still doesn't look quite right because the slot highlight is behind the item, but it'll do
|
||||
// until/unless I find a better solution.
|
||||
DrawingUtils.drawItemAndTooltip(gui, trade.getItemToSell(), slot.xPos, slot.yPos, event.getMouseX(), event.getMouseY(),
|
||||
gui.getSlotUnderMouse() == slot);
|
||||
}
|
||||
// Bow zoom. Taken directly from AbstractClientPlayer so it works exactly like vanilla.
|
||||
if(event.getEntity().isHandActive()){
|
||||
|
||||
Item item = event.getEntity().getActiveItemStack().getItem();
|
||||
|
||||
if(item instanceof ItemSpectralBow || item instanceof ItemFlamecatcher){
|
||||
|
||||
int maxUseTicks = event.getEntity().getItemInUseMaxCount();
|
||||
|
||||
float maxUseSeconds = (float)maxUseTicks / (item instanceof ItemFlamecatcher ? ItemFlamecatcher.DRAW_TIME : 20);
|
||||
|
||||
if(maxUseSeconds > 1.0F){
|
||||
maxUseSeconds = 1.0F;
|
||||
}else{
|
||||
maxUseSeconds = maxUseSeconds * maxUseSeconds;
|
||||
}
|
||||
|
||||
event.setNewfov(event.getFov() * 1.0F - maxUseSeconds * 0.15F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Post<EntityLivingBase> event){
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
WizardData data = WizardData.get(mc.player);
|
||||
RenderManager renderManager = event.getRenderer().getRenderManager();
|
||||
|
||||
ItemStack wand = mc.player.getHeldItemMainhand();
|
||||
|
||||
if(!(wand.getItem() instanceof ISpellCastingItem)){
|
||||
wand = mc.player.getHeldItemOffhand();
|
||||
}
|
||||
|
||||
// Target selection pointer
|
||||
if(mc.player.isSneaking() && wand.getItem() instanceof ISpellCastingItem && WizardryUtilities.isLiving(event.getEntity())
|
||||
&& data != null && data.selectedMinion != null){
|
||||
|
||||
// -> Moved this in here so it isn't called every tick
|
||||
RayTraceResult rayTrace = RayTracer.standardEntityRayTrace(mc.world, mc.player, 16, false);
|
||||
|
||||
if(rayTrace != null && rayTrace.entityHit == event.getEntity()){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
// Disabling depth test allows it to be seen through everything.
|
||||
GlStateManager.disableDepth();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
|
||||
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height + 0.5, event.getZ());
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = mc.gameSettings.thirdPersonView == 2 ? renderManager.playerViewX : -renderManager.playerViewX;
|
||||
GlStateManager.rotate(180 - renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
mc.renderEngine.bindTexture(targetPointerTexture);
|
||||
|
||||
buffer.pos(-0.2, 0.24, 0).tex(0, 0).endVertex();
|
||||
buffer.pos(0.2, 0.24, 0).tex(9f / 16f, 0).endVertex();
|
||||
buffer.pos(0.2, -0.24, 0).tex(9f / 16f, 11f / 16f).endVertex();
|
||||
buffer.pos(-0.2, -0.24, 0).tex(0, 11f / 16f).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableCull();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.enableDepth();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
// Summoned creature selection pointer
|
||||
if(data != null && data.selectedMinion != null && data.selectedMinion.get() == event.getEntity()){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
// Disabling depth test allows it to be seen through everything.
|
||||
GlStateManager.disableDepth();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
|
||||
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height + 0.5, event.getZ());
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = mc.gameSettings.thirdPersonView == 2 ? renderManager.playerViewX : -renderManager.playerViewX;
|
||||
GlStateManager.rotate(180 - renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
mc.renderEngine.bindTexture(pointerTexture);
|
||||
|
||||
buffer.pos(-0.2, 0.24, 0).tex(0, 0).endVertex();
|
||||
buffer.pos(0.2, 0.24, 0).tex(9f / 16f, 0).endVertex();
|
||||
buffer.pos(0.2, -0.24, 0).tex(9f / 16f, 11f / 16f).endVertex();
|
||||
buffer.pos(-0.2, -0.24, 0).tex(0, 11f / 16f).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableCull();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.enableDepth();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
// Sixth sense
|
||||
if(mc.player.isPotionActive(WizardryPotions.sixth_sense) && !(event.getEntity() instanceof EntityArmorStand)
|
||||
&& event.getEntity() != mc.player && mc.player.getActivePotionEffect(WizardryPotions.sixth_sense) != null
|
||||
&& event.getEntity().getDistance(mc.player) < Spells.sixth_sense.getProperty(Spell.EFFECT_RADIUS).floatValue()
|
||||
* (1 + mc.player.getActivePotionEffect(WizardryPotions.sixth_sense).getAmplifier() * Constants.RANGE_INCREASE_PER_LEVEL)){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
// Disabling depth test allows it to be seen through everything.
|
||||
GlStateManager.disableDepth();
|
||||
|
||||
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height * 0.6, event.getZ());
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = mc.gameSettings.thirdPersonView == 2 ? renderManager.playerViewX : -renderManager.playerViewX;
|
||||
GlStateManager.rotate(180 - renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
mc.renderEngine.bindTexture(sixthSenseTexture);
|
||||
|
||||
buffer.pos(-0.6, 0.6, 0).tex(0, 0).endVertex();
|
||||
buffer.pos(0.6, 0.6, 0).tex(1, 0).endVertex();
|
||||
buffer.pos(0.6, -0.6, 0).tex(1, 1).endVertex();
|
||||
buffer.pos(-0.6, -0.6, 0).tex(0, 1).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableCull();
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.enableDepth();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGameOverlayEvent(RenderGameOverlayEvent.Post event){
|
||||
|
||||
if(event.getType() == RenderGameOverlayEvent.ElementType.HELMET){
|
||||
|
||||
if(Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.sixth_sense)){
|
||||
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
GlStateManager.disableAlpha();
|
||||
|
||||
renderScreenOverlay(event, sixthSenseOverlayTexture);
|
||||
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
if(Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.frost)){
|
||||
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
GlStateManager.disableAlpha();
|
||||
|
||||
renderScreenOverlay(event, frostOverlayTexture);
|
||||
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
if(blinkEffectTimer > 0){
|
||||
|
||||
float alpha = ((float)blinkEffectTimer)/BLINK_EFFECT_DURATION;
|
||||
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GlStateManager.color(1, 1, 1, alpha);
|
||||
GlStateManager.disableAlpha();
|
||||
|
||||
renderScreenOverlay(event, blinkOverlayTexture);
|
||||
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderScreenOverlay(RenderGameOverlayEvent.Post event, ResourceLocation texture){
|
||||
/**
|
||||
* Renders an overlay across the entire screen.
|
||||
* @param resolution The screen resolution
|
||||
* @param texture The overlay texture to display
|
||||
*/
|
||||
public static void renderScreenOverlay(ScaledResolution resolution, ResourceLocation texture){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
@@ -471,11 +205,12 @@ public final class WizardryClientEventHandler {
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
buffer.pos(0.0D, (double)event.getResolution().getScaledHeight(), -90.0D).tex(0.0D, 1.0D).endVertex();
|
||||
buffer.pos((double)event.getResolution().getScaledWidth(), (double)event.getResolution().getScaledHeight(), -90.0D).tex(1.0D, 1.0D)
|
||||
.endVertex();
|
||||
buffer.pos((double)event.getResolution().getScaledWidth(), 0.0D, -90.0D).tex(1.0D, 0.0D).endVertex();
|
||||
buffer.pos(0.0D, 0.0D, -90.0D).tex(0.0D, 0.0D).endVertex();
|
||||
|
||||
buffer.pos(0, resolution.getScaledHeight(), -90).tex(0, 1).endVertex();
|
||||
buffer.pos(resolution.getScaledWidth(), resolution.getScaledHeight(), -90).tex(1, 1).endVertex();
|
||||
buffer.pos(resolution.getScaledWidth(), 0, -90).tex(1, 0).endVertex();
|
||||
buffer.pos(0, 0, -90).tex(0, 0).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.depthMask(true);
|
||||
|
||||
@@ -4,6 +4,7 @@ import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.gui.GuiSpellDisplay;
|
||||
import electroblob.wizardry.item.ISpellCastingItem;
|
||||
import electroblob.wizardry.packet.PacketControlInput;
|
||||
import electroblob.wizardry.packet.PacketSpellQuickAccess;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -24,6 +25,7 @@ public class WizardryControlHandler {
|
||||
|
||||
static boolean NkeyPressed = false;
|
||||
static boolean BkeyPressed = false;
|
||||
static boolean[] quickAccessKeyPressed = new boolean[ClientProxy.SPELL_QUICK_ACCESS.length];
|
||||
|
||||
// Changed to a tick event to allow mouse button keybinds
|
||||
// The 'lag' that happened previously was actually because the code only fired when a keyboard key was pressed!
|
||||
@@ -59,6 +61,19 @@ public class WizardryControlHandler {
|
||||
}else{
|
||||
BkeyPressed = false;
|
||||
}
|
||||
|
||||
for(int i = 0; i < ClientProxy.SPELL_QUICK_ACCESS.length; i++){
|
||||
if(ClientProxy.SPELL_QUICK_ACCESS[i].isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){
|
||||
if(!quickAccessKeyPressed[i]){
|
||||
quickAccessKeyPressed[i] = true;
|
||||
// Packet building
|
||||
selectSpell(wand, i);
|
||||
}
|
||||
}else{
|
||||
quickAccessKeyPressed[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,4 +133,17 @@ public class WizardryControlHandler {
|
||||
GuiSpellDisplay.playSpellSwitchAnimation(false);
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.ITEM_WAND_SWITCH_SPELL, 1));
|
||||
}
|
||||
|
||||
private static void selectSpell(ItemStack wand, int index){
|
||||
// GUI switch animation
|
||||
if(((ISpellCastingItem)wand.getItem()).selectSpell(wand, index)){ // Makes sure the spell is set immediately for the client
|
||||
// Packet building (no point sending it unless the client-side spell selection succeeded
|
||||
IMessage msg = new PacketSpellQuickAccess.Message(index);
|
||||
WizardryPacketHandler.net.sendToServer(msg);
|
||||
|
||||
GuiSpellDisplay.playSpellSwitchAnimation(true); // This will do, it's only an animation
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.ITEM_WAND_SWITCH_SPELL, 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package electroblob.wizardry.client.animation;
|
||||
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.item.SpellActions;
|
||||
import electroblob.wizardry.spell.Grapple;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import electroblob.wizardry.util.InventoryUtils;
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.util.EnumHandSide;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
/**
|
||||
* An animation that is associated with a particular {@link net.minecraft.item.EnumAction}. This animation will display
|
||||
* when a player is using an item with that action.
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
* @see electroblob.wizardry.item.SpellActions
|
||||
*/
|
||||
public abstract class ActionAnimation extends Animation {
|
||||
|
||||
private final EnumAction action;
|
||||
|
||||
public ActionAnimation(EnumAction action){
|
||||
super(action.name());
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDisplay(EntityPlayer player, boolean firstPerson){
|
||||
return !firstPerson && player.getItemInUseMaxCount() > 0 && player.getActiveItemStack().getItemUseAction() == action;
|
||||
}
|
||||
|
||||
/** Called from the client proxy to register all of wizardry's action animations. */
|
||||
public static void register(){
|
||||
|
||||
PlayerAnimator.registerAnimation(new ActionAnimation(SpellActions.POINT){
|
||||
@Override
|
||||
public void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson){
|
||||
// Something (probably some sort of race condition) causes getActiveItemStack to sometimes be wrong
|
||||
if(player.getActiveItemStack() != player.getHeldItem(player.getActiveHand())) return;
|
||||
|
||||
EnumHandSide side = InventoryUtils.getSideForHand(player, player.getActiveHand());
|
||||
|
||||
float pitch = (float)Math.toRadians(player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * partialTicks);
|
||||
float yaw = (float)Math.toRadians(player.prevRotationYawHead + (player.rotationYawHead - player.prevRotationYawHead) * partialTicks)
|
||||
- (float)Math.toRadians(player.prevRenderYawOffset + (player.renderYawOffset - player.prevRenderYawOffset) * partialTicks);
|
||||
|
||||
float x = -((float)Math.PI / 2) + pitch + 0.2f;
|
||||
float y = (side == EnumHandSide.RIGHT ? -0.25f : 0.25f) + yaw;
|
||||
|
||||
ModelRendererExtended arm = (ModelRendererExtended)getArmForSide(model, side);
|
||||
arm.setRotation(x, y, 0);
|
||||
}
|
||||
});
|
||||
|
||||
PlayerAnimator.registerAnimation(new ActionAnimation(SpellActions.POINT_UP){
|
||||
@Override
|
||||
public void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson){
|
||||
if(player.getActiveItemStack() != player.getHeldItem(player.getActiveHand())) return;
|
||||
EnumHandSide side = InventoryUtils.getSideForHand(player, player.getActiveHand());
|
||||
ModelRendererExtended arm = (ModelRendererExtended)getArmForSide(model, side);
|
||||
arm.addRotation(-2.2f, side == EnumHandSide.RIGHT ? 0.2f : -0.2f, 0);
|
||||
}
|
||||
});
|
||||
|
||||
PlayerAnimator.registerAnimation(new ActionAnimation(SpellActions.POINT_DOWN){
|
||||
@Override
|
||||
public void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson){
|
||||
float tick = player.getItemInUseMaxCount() + partialTicks; // It's not the "max" use count at all!
|
||||
float y = Math.min(0.4f + tick * 0.05f, 0.7f);
|
||||
EnumHandSide side = InventoryUtils.getSideForHand(player, player.getActiveHand());
|
||||
ModelRendererExtended arm = (ModelRendererExtended)getArmForSide(model, side);
|
||||
arm.addRotation(-0.2f, side == EnumHandSide.RIGHT ? y : -y, 0);
|
||||
}
|
||||
});
|
||||
|
||||
PlayerAnimator.registerAnimation(new ActionAnimation(SpellActions.SUMMON){
|
||||
@Override
|
||||
public void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson){
|
||||
float tick = player.getItemInUseMaxCount() + partialTicks; // It's not the "max" use count at all!
|
||||
float x = -Math.min(0.4f + tick * 0.2f, 2f);
|
||||
((ModelRendererExtended)getArmForSide(model, EnumHandSide.RIGHT)).addRotation(x, 1.2f, 0);
|
||||
((ModelRendererExtended)getArmForSide(model, EnumHandSide.LEFT)).addRotation(x, -1.2f, 0);
|
||||
}
|
||||
});
|
||||
|
||||
PlayerAnimator.registerAnimation(new ActionAnimation(SpellActions.GRAPPLE){
|
||||
@Override
|
||||
public void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson){
|
||||
|
||||
WizardData data = WizardData.get(player);
|
||||
RayTraceResult hit = data.getVariable(Grapple.TARGET_KEY);
|
||||
if(hit == null || hit.typeOfHit == RayTraceResult.Type.MISS) return;
|
||||
Vec3d target = hit.hitVec;
|
||||
|
||||
if(hit.entityHit instanceof EntityLivingBase){
|
||||
// If the target is an entity, we need to use the entity's centre rather than the original hit position
|
||||
// because the entity will have moved!
|
||||
target = GeometryUtils.getCentre(hit.entityHit);
|
||||
}
|
||||
|
||||
EnumHandSide side = InventoryUtils.getSideForHand(player, player.getActiveHand());
|
||||
|
||||
ModelRendererExtended arm = (ModelRendererExtended)getArmForSide(model, side);
|
||||
|
||||
Vec3d direction = target.subtract(player.getPositionEyes(partialTicks));
|
||||
float yaw = player.prevRenderYawOffset + (player.renderYawOffset - player.prevRenderYawOffset) * partialTicks;
|
||||
|
||||
float pitch = (float)MathHelper.atan2(MathHelper.sqrt(direction.x*direction.x + direction.z*direction.z), direction.y);
|
||||
float x = pitch - (float)Math.PI * 0.9f;
|
||||
float y = -(float)Math.toRadians(yaw) - (float)MathHelper.atan2(direction.x, direction.z);
|
||||
y += (side == EnumHandSide.RIGHT ? -0.25f : 0.25f);
|
||||
if(Math.abs(pitch) < 0.2f) y = arm.rotateAngleY;
|
||||
|
||||
arm.setRotation(x, y, 0);
|
||||
}
|
||||
});
|
||||
|
||||
PlayerAnimator.registerAnimation(new ActionAnimation(SpellActions.IMBUE){
|
||||
@Override
|
||||
public void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson){
|
||||
float tick = player.getItemInUseMaxCount() + partialTicks; // It's not the "max" use count at all!
|
||||
float z = Math.max(1.5f - tick * 0.1f, 0.8f);
|
||||
EnumHandSide side = InventoryUtils.getSideForHand(player, player.getActiveHand());
|
||||
ModelRendererExtended arm = (ModelRendererExtended)getArmForSide(model, side);
|
||||
arm.addRotation(-1.2f, side == EnumHandSide.RIGHT ? -0.2f : 0.2f, side == EnumHandSide.RIGHT ? z : -z);
|
||||
if(!player.getHeldItem(InventoryUtils.getHandForSide(player, side.opposite())).isEmpty()){
|
||||
((ModelRendererExtended)getArmForSide(model, side.opposite())).addRotation(-0.8f, side == EnumHandSide.LEFT ? 0.3f : -0.3f, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
PlayerAnimator.registerAnimation(new ActionAnimation(SpellActions.THRUST){
|
||||
@Override
|
||||
public void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson){
|
||||
if(player.getActiveItemStack() != player.getHeldItem(player.getActiveHand())) return;
|
||||
EnumHandSide side = InventoryUtils.getSideForHand(player, player.getActiveHand());
|
||||
ModelRendererExtended arm = (ModelRendererExtended)getArmForSide(model, side);
|
||||
float y = side == EnumHandSide.RIGHT ? -0.6f : 0.6f;
|
||||
arm.addRotation(-1.2f, y, 0);
|
||||
if(player.getHeldItem(InventoryUtils.getHandForSide(player, side.opposite())).isEmpty()){
|
||||
ModelRendererExtended otherArm = (ModelRendererExtended)getArmForSide(model, side.opposite());
|
||||
otherArm.setRotation(arm.rotateAngleX - 1.2f, -arm.rotateAngleY - y, otherArm.rotateAngleZ);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package electroblob.wizardry.client.animation;
|
||||
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.EnumHandSide;
|
||||
|
||||
/**
|
||||
* Represents a player animation. Use one of the predefined subclasses below for common animation types, or extend this
|
||||
* class directly to define a completely custom animation. Register instances of this class using
|
||||
* {@link PlayerAnimator#registerAnimation(Animation)}.
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
* @see ActionAnimation
|
||||
*/
|
||||
public abstract class Animation {
|
||||
|
||||
private final String name;
|
||||
|
||||
public Animation(String name){
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/** Returns the name of this animation, currently only used for warning messages / debugging. */
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this animation should be displayed for the given player. <i>Note that if two registered
|
||||
* animations have overlapping conditions, both will attempt to display simultaneously, so if they both animate the
|
||||
* same model part, that part may not behave as expected.</i>
|
||||
* @param player The player being animated
|
||||
* @param firstPerson True if the player being animated is the local client player, and they are in first-person
|
||||
* view. In first-person, animations are only useful for animating the player's empty hand.
|
||||
* @return True if the animation should be displayed, false if not.
|
||||
*/
|
||||
public abstract boolean shouldDisplay(EntityPlayer player, boolean firstPerson);
|
||||
|
||||
/**
|
||||
* Sets the rotation of the model parts for this animation. This method is called every time the player is rendered
|
||||
* when {@link Animation#shouldDisplay(EntityPlayer, boolean)} returns true.
|
||||
* @param player The player being animated
|
||||
* @param model The model to animate. All of the standard {@link ModelBiped} parts will already be wrapped and may
|
||||
* be safely cast to {@code ModelRendererExtended} in order to override the rotations set by the model
|
||||
* itself - see {@link ModelRendererExtended ModelRendererExtended} for details.
|
||||
* @param partialTicks The current partial tick time
|
||||
* @param firstPerson True if the player being animated is the local client player, and they are in first-person
|
||||
* view. In first-person, animations are only useful for animating the player's empty hand.
|
||||
*/
|
||||
public abstract void setRotationAngles(EntityPlayer player, ModelBiped model, float partialTicks, boolean firstPerson);
|
||||
|
||||
/**
|
||||
* Returns whether the boxes that form the second layer of the player's skin (for models that are instances of
|
||||
* {@link net.minecraft.client.model.ModelPlayer ModelPlayer}) should automatically be set to the same angles as
|
||||
* their corresponding first-layer parts.
|
||||
* @param player The player being rendered, for reference
|
||||
* @param firstPerson True if the player being animated is the local client player, and they are in first-person
|
||||
* view. In first-person, animations are only useful for animating the player's empty hand.
|
||||
* @return True to let {@link PlayerAnimator} auto-rotate the second skin layer, false to rotate them manually.
|
||||
*/
|
||||
public boolean autoRotateSecondLayer(EntityPlayer player, boolean firstPerson){
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arm of the given model corresponding to the given side. Function is identical to the method of the
|
||||
* same name in {@link ModelBiped}.
|
||||
* @param model The model to get the arm of
|
||||
* @param side The {@link EnumHandSide} to return the arm for
|
||||
* @return The {@link ModelRenderer} corresponding to the given arm
|
||||
*/
|
||||
public static ModelRenderer getArmForSide(ModelBiped model, EnumHandSide side){
|
||||
return side == EnumHandSide.LEFT ? model.bipedLeftArm : model.bipedRightArm;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package electroblob.wizardry.client.animation;
|
||||
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.client.model.ModelPlayer;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
|
||||
/**
|
||||
* A wrapper around {@link ModelRenderer} which can be swapped into models to allow render pre/post events to
|
||||
* circumvent {@code ModelBase.setRotationAngles(...)} and set model part rotations themselves. Instances of this class
|
||||
* keep a reference to the original {@code ModelRenderer} and delegate all the actual rendering to it.
|
||||
* <p></p>
|
||||
* {@link PlayerAnimator PlayerAnimator} does all the necessary setup with this
|
||||
* class for player animations. It is also possible to set up custom animations for non-player entities with this class,
|
||||
* see {@link ModelRendererExtended#wrap(ModelBiped)} and {@link ModelRendererExtended#wrap(ModelBase, ModelRenderer)}.
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
public class ModelRendererExtended extends ModelRenderer {
|
||||
|
||||
// We probably could have copied all the fields over instead, but this way if anyone else modifies the boxes we
|
||||
// won't overwrite their changes
|
||||
// This way also avoids reflection because we don't need to copy private fields, which is better for performance
|
||||
private ModelRenderer delegate;
|
||||
|
||||
private float actualRotationX;
|
||||
private float actualRotationY;
|
||||
private float actualRotationZ;
|
||||
|
||||
private float extraRotationX;
|
||||
private float extraRotationY;
|
||||
private float extraRotationZ;
|
||||
|
||||
private ModelRendererExtended(ModelBase baseModel, ModelRenderer delegate){
|
||||
super(baseModel, delegate.boxName);
|
||||
this.delegate = delegate;
|
||||
// Copy over any public fields that might get changed
|
||||
this.textureWidth = delegate.textureWidth;
|
||||
this.textureHeight = delegate.textureHeight;
|
||||
this.showModel = delegate.showModel;
|
||||
this.isHidden = delegate.isHidden;
|
||||
this.rotationPointX = delegate.rotationPointX;
|
||||
this.rotationPointY = delegate.rotationPointY;
|
||||
this.rotationPointZ = delegate.rotationPointZ;
|
||||
this.resetRotation();
|
||||
}
|
||||
|
||||
// Static initialisers
|
||||
|
||||
/**
|
||||
* Replaces the given part of the given {@link ModelBase} with a new {@code ModelRendererExtended} that wraps the
|
||||
* original part. This method takes care of modifying the model's box list, but <b>is unable to change any
|
||||
* individual {@link ModelRenderer} fields</b> - this method instead returns the resulting
|
||||
* {@code ModelRendererExtended} to be assigned to the appropriate field.
|
||||
* @param model The model whose part is to be wrapped
|
||||
* @param box The part of the model to wrap, must belong to the above model
|
||||
* @return The resulting wrapped model part, this should be assigned to the appropriate part field in the model. If
|
||||
* the given model part was already wrapped, this method simply returns it unchanged.
|
||||
* @throws IllegalArgumentException if the given box does not belong to the given model
|
||||
*/
|
||||
public static ModelRendererExtended wrap(ModelBase model, ModelRenderer box){
|
||||
if(box instanceof ModelRendererExtended) return (ModelRendererExtended)box; // Ignore already-wrapped parts
|
||||
ModelRendererExtended wrapper = new ModelRendererExtended(model, box);
|
||||
int index = model.boxList.indexOf(box);
|
||||
if(index < 0) throw new IllegalArgumentException(String.format("The given ModelRenderer %s does not belong to the given model %s", box, model));
|
||||
model.boxList.set(index, wrapper); // I doubt the order matters but we may as well put it at the same index
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the given {@link ModelBiped}'s parts with new {@code ModelRendererExtended} versions that wrap the
|
||||
* original parts. If the given model is a {@link ModelPlayer}, the extra boxes for player skin overlays will also
|
||||
* be wrapped.
|
||||
*/
|
||||
public static void wrap(ModelBiped model){
|
||||
// MMmmmmmm wraps
|
||||
model.bipedHead = wrap(model, model.bipedHead);
|
||||
model.bipedBody = wrap(model, model.bipedBody);
|
||||
model.bipedRightArm = wrap(model, model.bipedRightArm);
|
||||
model.bipedLeftArm = wrap(model, model.bipedLeftArm);
|
||||
model.bipedRightLeg = wrap(model, model.bipedRightLeg);
|
||||
model.bipedLeftLeg = wrap(model, model.bipedLeftLeg);
|
||||
model.bipedHeadwear = wrap(model, model.bipedHeadwear);
|
||||
|
||||
if(model instanceof ModelPlayer){
|
||||
((ModelPlayer)model).bipedBodyWear = wrap(model, ((ModelPlayer)model).bipedBodyWear);
|
||||
((ModelPlayer)model).bipedRightArmwear = wrap(model, ((ModelPlayer)model).bipedRightArmwear);
|
||||
((ModelPlayer)model).bipedLeftArmwear = wrap(model, ((ModelPlayer)model).bipedLeftArmwear);
|
||||
((ModelPlayer)model).bipedRightLegwear = wrap(model, ((ModelPlayer)model).bipedRightLegwear);
|
||||
((ModelPlayer)model).bipedLeftLegwear = wrap(model, ((ModelPlayer)model).bipedLeftLegwear);
|
||||
}
|
||||
}
|
||||
|
||||
/** Resets the rotation of this model part to the angle set by the parent model. */
|
||||
public void resetRotation(){
|
||||
this.actualRotationX = Float.NaN;
|
||||
this.actualRotationY = Float.NaN;
|
||||
this.actualRotationZ = Float.NaN;
|
||||
this.extraRotationX = 0;
|
||||
this.extraRotationY = 0;
|
||||
this.extraRotationZ = 0;
|
||||
}
|
||||
|
||||
/** Sets the rotation of this model part, which will overwrite the angle set by the parent model. */
|
||||
public void setRotation(float x, float y, float z){
|
||||
this.actualRotationX = x;
|
||||
this.actualRotationY = y;
|
||||
this.actualRotationZ = z;
|
||||
}
|
||||
|
||||
/** Sets the extra rotation of this model part, which will be added onto the angle set by the parent model. */
|
||||
public void addRotation(float x, float y, float z){
|
||||
this.extraRotationX = x;
|
||||
this.extraRotationY = y;
|
||||
this.extraRotationZ = z;
|
||||
}
|
||||
|
||||
/** Sets the rotation of this model part to the same values as the given box. */
|
||||
public void setRotationTo(ModelRendererExtended box){
|
||||
this.actualRotationX = box.actualRotationX;
|
||||
this.actualRotationY = box.actualRotationY;
|
||||
this.actualRotationZ = box.actualRotationZ;
|
||||
this.extraRotationX = box.extraRotationX;
|
||||
this.extraRotationY = box.extraRotationY;
|
||||
this.extraRotationZ = box.extraRotationZ;
|
||||
}
|
||||
|
||||
// Delegate rendering, but fiddle with the angles first
|
||||
|
||||
@Override
|
||||
public void render(float scale){
|
||||
|
||||
// Need to copy these over each time in case they were changed
|
||||
delegate.showModel = this.showModel;
|
||||
delegate.isHidden = this.isHidden;
|
||||
delegate.rotationPointX = this.rotationPointX;
|
||||
delegate.rotationPointY = this.rotationPointY;
|
||||
delegate.rotationPointZ = this.rotationPointZ;
|
||||
|
||||
if(!Float.isNaN(actualRotationX) && !Float.isNaN(actualRotationY) && !Float.isNaN(actualRotationZ)){
|
||||
delegate.rotateAngleX = actualRotationX;
|
||||
delegate.rotateAngleY = actualRotationY;
|
||||
delegate.rotateAngleZ = actualRotationZ;
|
||||
}else{
|
||||
delegate.rotateAngleX = this.rotateAngleX + extraRotationX;
|
||||
delegate.rotateAngleY = this.rotateAngleY + extraRotationY;
|
||||
delegate.rotateAngleZ = this.rotateAngleZ + extraRotationZ;
|
||||
}
|
||||
|
||||
delegate.render(scale);
|
||||
}
|
||||
|
||||
// Delegate all other methods
|
||||
|
||||
@Override
|
||||
public void addChild(ModelRenderer renderer){
|
||||
delegate.addChild(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWithRotation(float scale){
|
||||
delegate.renderWithRotation(scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postRender(float scale){
|
||||
// Exactly the same setup as above, just add item rotation/translation fields and setters
|
||||
// float angle = 1;
|
||||
// float radius = 10;
|
||||
// delegate.rotationPointY -= radius * MathHelper.cos(angle);
|
||||
// delegate.rotationPointZ -= radius * MathHelper.sin(angle);
|
||||
// delegate.rotateAngleX += angle;
|
||||
delegate.postRender(scale);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
package electroblob.wizardry.client.animation;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.item.SpellActions;
|
||||
import electroblob.wizardry.util.InventoryUtils;
|
||||
import electroblob.wizardry.util.JavaUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.AbstractClientPlayer;
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.client.model.ModelPlayer;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.client.renderer.entity.RenderPlayer;
|
||||
import net.minecraft.client.renderer.entity.layers.LayerBipedArmor;
|
||||
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.EnumHandSide;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.client.event.RenderSpecificHandEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Handles the setup and rendering events for custom player animations, as well as registering of animations. Addons
|
||||
* can also register their own animations here, see {@link PlayerAnimator#registerAnimation(Animation)}.
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
* @see electroblob.wizardry.item.SpellActions SpellActions
|
||||
*/
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public class PlayerAnimator {
|
||||
|
||||
// TODO: Attempt to extend this to all bipeds
|
||||
|
||||
private static final List<Animation> animations = new ArrayList<>();
|
||||
|
||||
/** Stores all registered layer renderers for lazy-loading of armour models later. */
|
||||
private static final Map<RenderPlayer, List<LayerRenderer<? extends EntityLivingBase>>> playerLayers = new HashMap<>();
|
||||
/** Stores the main model for each renderer plus all models for registered layer renderers. */
|
||||
private static final Map<RenderPlayer, List<ModelBiped>> playerLayerModels = new HashMap<>();
|
||||
/** Reflected into {@link RenderLivingBase}{@code #layerRenderers}. */
|
||||
private static final Field layerRenderers;
|
||||
|
||||
static {
|
||||
layerRenderers = ObfuscationReflectionHelper.findField(RenderLivingBase.class, "field_177097_h");
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new player animation. This method should be called from the {@code init()} phase via a client proxy.
|
||||
* @param animation The animation to register
|
||||
*/
|
||||
// N.B. This can (and will) be called before PlayerAnimator#init() is called
|
||||
public static void registerAnimation(Animation animation){
|
||||
if(animations.contains(animation)){
|
||||
Wizardry.logger.warn("Animation {} is already registered!", animation.getName());
|
||||
}else{
|
||||
animations.add(animation);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Figure out if calling this from postInit ensures we catch all the layers, and lazy-load it if not
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void init(){
|
||||
|
||||
if(!Wizardry.settings.spellcastingAnimations) return;
|
||||
|
||||
for(RenderPlayer renderer : Minecraft.getMinecraft().getRenderManager().getSkinMap().values()){
|
||||
|
||||
List<ModelBiped> models = new ArrayList<>();
|
||||
ModelRendererExtended.wrap(renderer.getMainModel());
|
||||
models.add(renderer.getMainModel());
|
||||
|
||||
try {
|
||||
|
||||
List<LayerRenderer<? extends EntityLivingBase>> layers = (List<LayerRenderer<? extends EntityLivingBase>>)layerRenderers.get(renderer);
|
||||
|
||||
// Save armour layers for lazy-loading later (ignore other layers so iteration is faster)
|
||||
playerLayers.put(renderer, layers.stream().filter(l -> l instanceof LayerBipedArmor).collect(Collectors.toList()));
|
||||
|
||||
for(LayerRenderer<?> layer : layers){
|
||||
|
||||
for(Field field : JavaUtils.getAllFields(layer.getClass())){
|
||||
|
||||
field.setAccessible(true);
|
||||
|
||||
// If your layer model doesn't extend ModelBiped, you DESERVE to be incompatible!
|
||||
// (Just kidding... there's nothing I can do about it anyway)
|
||||
if(field.get(layer) instanceof ModelBiped){
|
||||
ModelBiped model = (ModelBiped)field.get(layer);
|
||||
ModelRendererExtended.wrap(model);
|
||||
models.add(model);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}catch(IllegalAccessException e){
|
||||
Wizardry.logger.error("Error during reflective access of render layers: ", e);
|
||||
}
|
||||
|
||||
playerLayerModels.put(renderer, models);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateModels(EntityPlayer player, Render<?> renderer, float partialTicks, boolean firstPerson){
|
||||
|
||||
// Biped armour is special because of Forge's armour item render hook
|
||||
// This needs to be lazy-loaded because we need access to an actual item
|
||||
for(LayerRenderer<? extends EntityLivingBase> layer : playerLayers.get(renderer)){
|
||||
if(layer instanceof LayerBipedArmor){
|
||||
for(EntityEquipmentSlot slot : InventoryUtils.ARMOUR_SLOTS){
|
||||
|
||||
ItemStack armour = player.getItemStackFromSlot(slot);
|
||||
// This method could behave dynamically depending on stuff like NBT so there's not really any way to
|
||||
// optimise it further, we *have* to retrieve the model every time (shouldn't be too bad though)
|
||||
ModelBiped model = ForgeHooksClient.getArmorModel(player, armour, slot, ((LayerBipedArmor)layer).getModelFromSlot(slot));
|
||||
|
||||
List<ModelBiped> models = playerLayerModels.get(renderer);
|
||||
|
||||
if(!models.contains(model)){ // Ignore already-wrapped models
|
||||
models.add(model);
|
||||
ModelRendererExtended.wrap(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(Animation animation : animations){
|
||||
|
||||
if(animation.shouldDisplay(player, firstPerson)){
|
||||
|
||||
boolean autoRotateSecondLayer = animation.autoRotateSecondLayer(player, firstPerson);
|
||||
|
||||
for(ModelBiped model : playerLayerModels.get(renderer)){
|
||||
|
||||
animation.setRotationAngles(player, model, partialTicks, firstPerson);
|
||||
|
||||
if(autoRotateSecondLayer && model instanceof ModelPlayer){
|
||||
alignSecondLayer((ModelPlayer)model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Rotates the second layer boxes of the given (wrapped) player model to match the first layer. */
|
||||
public static void alignSecondLayer(ModelPlayer model){
|
||||
((ModelRendererExtended)model.bipedBodyWear) .setRotationTo((ModelRendererExtended)model.bipedBody);
|
||||
((ModelRendererExtended)model.bipedRightArmwear).setRotationTo((ModelRendererExtended)model.bipedRightArm);
|
||||
((ModelRendererExtended)model.bipedLeftArmwear) .setRotationTo((ModelRendererExtended)model.bipedLeftArm);
|
||||
((ModelRendererExtended)model.bipedRightLegwear).setRotationTo((ModelRendererExtended)model.bipedBody);
|
||||
((ModelRendererExtended)model.bipedLeftLegwear) .setRotationTo((ModelRendererExtended)model.bipedBody);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderHandEvent(RenderSpecificHandEvent event){
|
||||
|
||||
if(!Wizardry.settings.spellcastingAnimations) return;
|
||||
|
||||
AbstractClientPlayer player = Minecraft.getMinecraft().player;
|
||||
|
||||
EnumAction action = event.getItemStack().getItemUseAction();
|
||||
|
||||
if(player.isHandActive() && player.getActiveHand() == event.getHand() && SpellActions.getSpellActions().contains(action)){
|
||||
// Minecraft's item renderer helpfully doesn't have a default case for the usage action so it doesn't do any
|
||||
// transformations at all (which is VERY ANNOYING!) - the following lines are from ItemRenderer#transformSideFirstPerson
|
||||
int i = (player.getPrimaryHand() == EnumHandSide.RIGHT) == (event.getHand() == EnumHand.MAIN_HAND) ? 1 : -1;
|
||||
GlStateManager.translate((float)i * 0.56F, -0.52F + event.getEquipProgress() * -0.6F, -0.72F);
|
||||
}
|
||||
|
||||
updateModels(player, Minecraft.getMinecraft().getRenderManager().getEntityRenderObject(player), event.getPartialTicks(), true);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerPreEvent(RenderPlayerEvent.Pre event){
|
||||
|
||||
if(!Wizardry.settings.spellcastingAnimations) return;
|
||||
|
||||
// boolean firstPerson = event.getEntityPlayer() == Minecraft.getMinecraft().player
|
||||
// && Minecraft.getMinecraft().gameSettings.thirdPersonView == 0;
|
||||
|
||||
updateModels(event.getEntityPlayer(), event.getRenderer(), event.getPartialRenderTick(), false);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerPostEvent(RenderPlayerEvent.Post event){
|
||||
|
||||
if(!Wizardry.settings.spellcastingAnimations) return;
|
||||
|
||||
for(ModelBiped model : playerLayerModels.get(event.getRenderer())){
|
||||
for(ModelRenderer box : model.boxList){ // For ModelPlayer, this will include the second layer
|
||||
// Some models have extra boxes, they (probably) don't need wrapping but we need this check!
|
||||
if(box instanceof ModelRendererExtended){
|
||||
((ModelRendererExtended)box).resetRotation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package electroblob.wizardry.client.audio;
|
||||
|
||||
import electroblob.wizardry.item.ISpellCastingItem;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
|
||||
/** A special type of moving sound that stops when the player stops charging up a spell, either by releasing the mouse
|
||||
* button or when the charge-up time has elapsed. */
|
||||
public class MovingSoundSpellCharge extends MovingSoundEntity<EntityLivingBase> {
|
||||
|
||||
public MovingSoundSpellCharge(EntityLivingBase entity, SoundEvent sound, SoundCategory category, float volume, float pitch, boolean repeat){
|
||||
super(entity, sound, category, volume, pitch, repeat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
|
||||
if(source.isHandActive()){
|
||||
|
||||
ItemStack stack = source.getActiveItemStack();
|
||||
|
||||
if(stack.getItem() instanceof ISpellCastingItem){
|
||||
|
||||
if(source.getItemInUseMaxCount() < ((ISpellCastingItem)stack.getItem()).getCurrentSpell(stack).getChargeup()){
|
||||
super.update();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.donePlaying = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,16 @@ public abstract class SoundLoop implements ITickable {
|
||||
|
||||
private static final Set<SoundLoop> activeLoops = new HashSet<>();
|
||||
|
||||
// The issue we had here was that there is no way of hooking into the client tick loop between the sound manager
|
||||
// update and the world tick (other than via the sounds themselves, but playing other sounds from there results in
|
||||
// CMEs, which is why we made this class in the first place). This meant there was always a gap between consecutive
|
||||
// sounds, which could be heard in-game as a weird audio artefact. The solution is simply to overlap the sounds by
|
||||
// 1 tick, which is fairly straightforward for the end sound, but because the start sound has to finish for us to
|
||||
// know when to play the others, this doubling-up solution is required (bit of a waste of resources but meh).
|
||||
/** A dummy sound with effectively zero volume, played one tick in advance of the actual start sound so the loop
|
||||
* sound can start one tick before the actual start sound ends. */
|
||||
private final ISound dummyStart; // It's the stupidest system ever but it works!
|
||||
|
||||
private final ISound start;
|
||||
private final ISound loop;
|
||||
private final ISound end;
|
||||
@@ -34,29 +44,28 @@ public abstract class SoundLoop implements ITickable {
|
||||
private boolean looping = false;
|
||||
private boolean needsRemoving = false;
|
||||
|
||||
public SoundLoop(SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, ISoundFactory factory){
|
||||
public SoundLoop(SoundEvent start, SoundEvent loop, SoundEvent end, SoundCategory category, float volume, ISoundFactory factory){
|
||||
// The reason I've gone to the effort of having a factory for these is that we need SoundLoop to have control
|
||||
// over which sounds are repeated and which aren't whilst keeping them private.
|
||||
this.start = factory.create(start, category, false);
|
||||
this.loop = factory.create(loop, category, true);
|
||||
this.end = factory.create(end, category, false);
|
||||
this.dummyStart = factory.create(start, category, 0.00001f, false); // Inaudible but not actually 0
|
||||
this.start = factory.create(start, category, volume, false);
|
||||
this.loop = factory.create(loop, category, volume, true);
|
||||
this.end = factory.create(end, category, volume, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
// Check every tick if the start sound is done playing and if so, start the loop sound
|
||||
if(!looping && !Minecraft.getMinecraft().getSoundHandler().isSoundPlaying(start)){
|
||||
if(!looping && !Minecraft.getMinecraft().getSoundHandler().isSoundPlaying(dummyStart)){
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(loop);
|
||||
looping = true;
|
||||
}
|
||||
}
|
||||
|
||||
/** Stops the loop part of the sound immediately and starts playing the end part. This may be called from subclasses
|
||||
* or externally depending on the implementation. */
|
||||
/** Starts playing the end part immediately and marks the loop part to stop next tick. This may be called from
|
||||
* subclasses or externally depending on the implementation. */
|
||||
// For continuous spell sounds it's internally
|
||||
public void endLoop(){
|
||||
Minecraft.getMinecraft().getSoundHandler().stopSound(start);
|
||||
Minecraft.getMinecraft().getSoundHandler().stopSound(loop);
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(end);
|
||||
// Can't modify activeLoops directly since we'll probably be calling this method from update(), which is
|
||||
// during iteration of activeLoops so it could cause a ConcurrentModificationException
|
||||
@@ -68,12 +77,20 @@ public abstract class SoundLoop implements ITickable {
|
||||
this.needsRemoving = true;
|
||||
}
|
||||
|
||||
/** Stops the start and loop sounds immediately. */
|
||||
protected void stopStartAndLoop(){
|
||||
Minecraft.getMinecraft().getSoundHandler().stopSound(dummyStart);
|
||||
Minecraft.getMinecraft().getSoundHandler().stopSound(start);
|
||||
Minecraft.getMinecraft().getSoundHandler().stopSound(loop);
|
||||
}
|
||||
|
||||
// Static methods
|
||||
|
||||
public static void addLoop(SoundLoop loop){
|
||||
activeLoops.add(loop);
|
||||
// Do this here rather than in the constructor in case someone wants to play the loop later or reuse it
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(loop.start);
|
||||
Minecraft.getMinecraft().getSoundHandler().playSound(loop.dummyStart);
|
||||
Minecraft.getMinecraft().getSoundHandler().playDelayedSound(loop.start, 2); // 1 seems to be insufficient
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -82,13 +99,14 @@ public abstract class SoundLoop implements ITickable {
|
||||
// meaning we don't get the 'cut' between the start and loop sounds
|
||||
// FIXME: Apparently this only works for dispensers. What the heck is the difference?!
|
||||
if(event.phase == TickEvent.Phase.END){
|
||||
activeLoops.forEach(SoundLoop::update);
|
||||
activeLoops.stream().filter(s -> s.needsRemoving).forEach(SoundLoop::stopStartAndLoop);
|
||||
activeLoops.removeIf(s -> s.needsRemoving);
|
||||
activeLoops.forEach(SoundLoop::update); // Do this last to allow a 1-tick overlap
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ISoundFactory {
|
||||
ISound create(SoundEvent sound, SoundCategory category, boolean repeat);
|
||||
ISound create(SoundEvent sound, SoundCategory category, float volume, boolean repeat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package electroblob.wizardry.client.audio;
|
||||
import electroblob.wizardry.data.DispenserCastingData;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import net.minecraft.client.audio.PositionedSound;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
@@ -17,8 +17,8 @@ public abstract class SoundLoopSpell extends SoundLoop {
|
||||
|
||||
private final Spell spell;
|
||||
|
||||
public SoundLoopSpell(SoundEvent start, SoundEvent loop, SoundEvent end, ISoundFactory factory, Spell spell){
|
||||
super(start, loop, end, WizardrySounds.SPELLS, factory);
|
||||
public SoundLoopSpell(SoundEvent start, SoundEvent loop, SoundEvent end, float volume, ISoundFactory factory, Spell spell){
|
||||
super(start, loop, end, WizardrySounds.SPELLS, volume, factory);
|
||||
this.spell = spell;
|
||||
}
|
||||
|
||||
@@ -43,13 +43,13 @@ public abstract class SoundLoopSpell extends SoundLoop {
|
||||
private final EntityLivingBase source;
|
||||
|
||||
public SoundLoopSpellEntity(SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell, EntityLivingBase source, float volume, float pitch){
|
||||
super(start, loop, end, (sound, category, repeat) -> new MovingSoundEntity<>(source, sound, category, volume, pitch, repeat), spell);
|
||||
super(start, loop, end, volume, (sound, category, v, repeat) -> new MovingSoundEntity<>(source, sound, category, v, pitch, repeat), spell);
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean stillCasting(Spell spell){
|
||||
return WizardryUtilities.isCasting(source, spell);
|
||||
return EntityUtils.isCasting(source, spell);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ public abstract class SoundLoopSpell extends SoundLoop {
|
||||
public SoundLoopSpellPosition (SoundEvent start, SoundEvent loop, SoundEvent end, Spell spell,
|
||||
double x, double y, double z, float sndVolume, float sndPitch){
|
||||
// Huh, I actually found a use for a non-static initialiser block - hence the double curly brackets...
|
||||
super(start, loop, end, (sound, category, r) -> new PositionedSound(sound, category){{
|
||||
super(start, loop, end, sndVolume, (sound, category, v, r) -> new PositionedSound(sound, category){{
|
||||
// ...et voila, we can just set protected fields as we please using external variables
|
||||
this.xPosF = (float)x;
|
||||
this.yPosF = (float)y;
|
||||
this.zPosF = (float)z;
|
||||
this.repeat = r;
|
||||
this.volume = sndVolume;
|
||||
this.volume = v;
|
||||
this.pitch = sndPitch;
|
||||
}}, spell);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.registry.WizardryTabs;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.util.text.Style;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Locale;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class CustomCreativeSearchHandler {
|
||||
|
||||
private static final int SEARCH_TOOLTIP_HOVER_TIME = 20;
|
||||
|
||||
private static final Style TOOLTIP_SYNTAX = new Style().setColor(TextFormatting.YELLOW);
|
||||
private static final Style TOOLTIP_BODY = new Style().setColor(TextFormatting.WHITE);
|
||||
|
||||
/** Reflected into {@code GuiContainerCreative#searchField} */
|
||||
private static final Field searchField;
|
||||
|
||||
private static GuiTextField currentSearchField = null;
|
||||
|
||||
private static int searchBarHoverTime;
|
||||
|
||||
static {
|
||||
searchField = ObfuscationReflectionHelper.findField(GuiContainerCreative.class, "field_147062_A");
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onInitGuiEvent(GuiScreenEvent.InitGuiEvent.Post event){
|
||||
// Reduces reflection as much as possible - searchField is created on GUI init and never reassigned so we need
|
||||
// not (and should not!) use reflection to retrieve it every time a key is typed
|
||||
if(event.getGui() instanceof GuiContainerCreative){
|
||||
try{
|
||||
currentSearchField = (GuiTextField)searchField.get(event.getGui());
|
||||
}catch(IllegalAccessException e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onKeyboardInputEvent(GuiScreenEvent.KeyboardInputEvent.Post event){
|
||||
// Custom creative tab search behaviour
|
||||
if(event.getGui() instanceof GuiContainerCreative){
|
||||
|
||||
GuiContainerCreative gui = (GuiContainerCreative)event.getGui();
|
||||
CreativeTabs tab = CreativeTabs.CREATIVE_TAB_ARRAY[gui.getSelectedTabIndex()];
|
||||
|
||||
if(tab == WizardryTabs.SPELLS){
|
||||
|
||||
GuiContainerCreative.ContainerCreative container = (GuiContainerCreative.ContainerCreative)gui.inventorySlots;
|
||||
container.itemList.clear(); // Required or duplicates will appear!
|
||||
String searchText = currentSearchField.getText().toLowerCase(Locale.ROOT);
|
||||
tab.displayAllRelevantItems(container.itemList);
|
||||
|
||||
if(!searchText.isEmpty()){
|
||||
container.itemList.removeIf(s -> !Spell.byMetadata(s.getMetadata()).matches(searchText));
|
||||
container.scrollTo(0); // Seems to refresh the GUI somehow so it displays correctly
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onClientTickEvent(ClientTickEvent event){
|
||||
if(event.phase == Phase.END && searchBarHoverTime > 0 && searchBarHoverTime < SEARCH_TOOLTIP_HOVER_TIME){
|
||||
searchBarHoverTime++;
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onDrawScreenPostEvent(GuiScreenEvent.DrawScreenEvent.Post event){
|
||||
|
||||
if(event.getGui() instanceof GuiContainerCreative && currentSearchField != null){
|
||||
|
||||
GuiContainerCreative gui = (GuiContainerCreative)event.getGui();
|
||||
CreativeTabs tab = CreativeTabs.CREATIVE_TAB_ARRAY[gui.getSelectedTabIndex()];
|
||||
|
||||
if(tab == WizardryTabs.SPELLS && DrawingUtils.isPointInRegion(currentSearchField.x, currentSearchField.y, currentSearchField.width, currentSearchField.height, event.getMouseX(), event.getMouseY())){
|
||||
|
||||
if(searchBarHoverTime == 0){
|
||||
searchBarHoverTime++;
|
||||
}else if(searchBarHoverTime == SEARCH_TOOLTIP_HOVER_TIME){
|
||||
event.getGui().drawHoveringText(I18n.format("container." + Wizardry.MODID + ":arcane_workbench.search_tooltip",
|
||||
TOOLTIP_SYNTAX.getFormattingCode(), TOOLTIP_BODY.getFormattingCode()), event.getMouseX(), event.getMouseY());
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
searchBarHoverTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.inventory.ContainerBookshelf;
|
||||
import electroblob.wizardry.tileentity.TileEntityBookshelf;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class GuiBookshelf extends GuiContainer {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/container/bookshelf.png");
|
||||
/** The player inventory bound to this GUI. */
|
||||
private final InventoryPlayer playerInventory;
|
||||
/** The inventory contained within the corresponding bookshelf. */
|
||||
public IInventory bookshelfInventory;
|
||||
|
||||
public GuiBookshelf(InventoryPlayer playerInv, TileEntityBookshelf bookshelfInv){
|
||||
super(new ContainerBookshelf(playerInv, bookshelfInv));
|
||||
this.playerInventory = playerInv;
|
||||
this.bookshelfInventory = bookshelfInv;
|
||||
this.allowUserInput = false;
|
||||
this.ySize = 148;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks){
|
||||
this.drawDefaultBackground();
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
this.renderHoveredToolTip(mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY){
|
||||
String s = this.bookshelfInventory.getDisplayName().getUnformattedText();
|
||||
this.fontRenderer.drawString(s, 8, 6, 4210752);
|
||||
this.fontRenderer.drawString(this.playerInventory.getDisplayName().getUnformattedText(), 8, this.ySize - 96 + 2, 4210752);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY){
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.mc.getTextureManager().bindTexture(TEXTURE);
|
||||
int i = (this.width - this.xSize) / 2;
|
||||
int j = (this.height - this.ySize) / 2;
|
||||
this.drawTexturedModalRect(i, j, 0, 0, this.xSize, this.ySize);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,8 +7,8 @@ import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.spell.Resurrection;
|
||||
import electroblob.wizardry.util.InventoryUtils;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiGameOver;
|
||||
@@ -52,7 +52,7 @@ public class GuiButtonResurrect extends GuiButton {
|
||||
public static void onGuiScreenInitEvent(GuiScreenEvent.InitGuiEvent event){
|
||||
|
||||
if(event.getGui() instanceof GuiGameOver && ItemArtefact.isArtefactActive(Minecraft.getMinecraft().player, WizardryItems.amulet_resurrection)
|
||||
&& WizardryUtilities.getHotbar(Minecraft.getMinecraft().player).stream().anyMatch(s -> Resurrection.canStackResurrect(s, Minecraft.getMinecraft().player))){
|
||||
&& InventoryUtils.getHotbar(Minecraft.getMinecraft().player).stream().anyMatch(s -> Resurrection.canStackResurrect(s, Minecraft.getMinecraft().player))){
|
||||
|
||||
event.getButtonList().add(new GuiButtonResurrect(event.getButtonList().size(), event.getGui().width / 2 - 100,
|
||||
event.getGui().height / 4 + 120, "spell." + Spells.resurrection.getRegistryName() + ".button"));
|
||||
@@ -65,7 +65,7 @@ public class GuiButtonResurrect extends GuiButton {
|
||||
|
||||
if(event.getGui() instanceof GuiGameOver){
|
||||
|
||||
ItemStack stack = WizardryUtilities.getHotbar(Minecraft.getMinecraft().player).stream()
|
||||
ItemStack stack = InventoryUtils.getHotbar(Minecraft.getMinecraft().player).stream()
|
||||
.filter(s -> Resurrection.canStackResurrect(s, Minecraft.getMinecraft().player)).findFirst().orElse(null);
|
||||
|
||||
if(stack != null){
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.util.ISpellSortable;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class GuiButtonSpellSort extends GuiButton {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/container/spell_sort_buttons.png");
|
||||
private static final int TEXTURE_WIDTH = 32;
|
||||
private static final int TEXTURE_HEIGHT = 32;
|
||||
|
||||
public final ISpellSortable.SortType sortType;
|
||||
|
||||
private final ISpellSortable sortable;
|
||||
private final GuiScreen parent;
|
||||
|
||||
public GuiButtonSpellSort(int id, int x, int y, ISpellSortable.SortType sortType, ISpellSortable sortable, GuiScreen parent){
|
||||
super(id, x, y, 10, 10, I18n.format("container." + Wizardry.MODID + ":arcane_workbench.sort_" + sortType.name));
|
||||
this.sortType = sortType;
|
||||
this.sortable = sortable;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
|
||||
|
||||
if(this.visible){
|
||||
|
||||
// Whether the button is highlighted
|
||||
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
|
||||
|
||||
int k = 0;
|
||||
int l = this.sortType.ordinal() * this.height;
|
||||
|
||||
if(sortType == sortable.getSortType()){
|
||||
k += this.width;
|
||||
if(sortable.isSortDescending()) k += this.width;
|
||||
}
|
||||
|
||||
parent.mc.getTextureManager().bindTexture(TEXTURE);
|
||||
DrawingUtils.drawTexturedRect(this.x, this.y, k, l, this.width, this.height, TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawButtonForegroundLayer(int mouseX, int mouseY){
|
||||
if(hovered) parent.drawHoveringText(this.displayString, mouseX, mouseY);
|
||||
}
|
||||
|
||||
}
|
||||
+14
-10
@@ -1,6 +1,5 @@
|
||||
package electroblob.wizardry.client.gui.handbook;
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -11,12 +10,12 @@ import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
//@SideOnly(Side.CLIENT)
|
||||
class GuiButtonTurnPage extends GuiButton {
|
||||
public class GuiButtonTurnPage extends GuiButton {
|
||||
|
||||
static final int WIDTH = 20;
|
||||
static final int HEIGHT = 12;
|
||||
public static final int WIDTH = 20;
|
||||
public static final int HEIGHT = 12;
|
||||
|
||||
enum Type {
|
||||
public enum Type {
|
||||
|
||||
NEXT_PAGE(0, 196),
|
||||
PREVIOUS_PAGE(0, 208),
|
||||
@@ -34,11 +33,15 @@ class GuiButtonTurnPage extends GuiButton {
|
||||
|
||||
public final Type type;
|
||||
|
||||
private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/handbook.png");
|
||||
private final ResourceLocation texture;
|
||||
private final int textureWidth, textureHeight;
|
||||
|
||||
public GuiButtonTurnPage(int id, int x, int y, Type type){
|
||||
public GuiButtonTurnPage(int id, int x, int y, Type type, ResourceLocation texture, int textureWidth, int textureHeight){
|
||||
super(id, x, y, WIDTH, HEIGHT, "");
|
||||
this.type = type;
|
||||
this.texture = texture;
|
||||
this.textureWidth = textureWidth;
|
||||
this.textureHeight = textureHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,12 +53,13 @@ class GuiButtonTurnPage extends GuiButton {
|
||||
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
|
||||
|
||||
if(this.visible){
|
||||
|
||||
|
||||
boolean flag = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
minecraft.getTextureManager().bindTexture(texture);
|
||||
|
||||
DrawingUtils.drawTexturedRect(this.x, this.y, flag ? type.u + width : type.u, type.v, width, height, 512, 256);
|
||||
DrawingUtils.drawTexturedRect(this.x, this.y, flag ? type.u + width : type.u, type.v, width, height, textureWidth, textureHeight);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,499 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockBookshelf;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.client.gui.GuiButtonTurnPage.Type;
|
||||
import electroblob.wizardry.data.SpellGlyphData;
|
||||
import electroblob.wizardry.item.ItemSpellBook;
|
||||
import electroblob.wizardry.packet.PacketLectern;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.tileentity.TileEntityLectern;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import electroblob.wizardry.util.ISpellSortable;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.audio.SoundHandler;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.play.client.CPacketCloseWindow;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.Style;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GuiLectern extends GuiSpellInfo implements ISpellSortable {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/container/lectern.png");
|
||||
/** The distance of the page buttons from the bottom outside corners of the GUI. */
|
||||
private static final int PAGE_BUTTON_INSET_X = 22, PAGE_BUTTON_INSET_Y = 13;
|
||||
/** The distance between adjacent page turn buttons. */
|
||||
private static final int PAGE_BUTTON_SPACING = 20;
|
||||
/** The distance of the sort buttons from the top left corner of the GUI. */
|
||||
private static final int SORT_BUTTON_INSET_X = 96, SORT_BUTTON_INSET_Y = 20;
|
||||
/** The distance between adjacent sort buttons. */
|
||||
private static final int SORT_BUTTON_SPACING = 13;
|
||||
/** The distance of the spell buttons from the top outside corners of the GUI. */
|
||||
private static final int SPELL_BUTTON_INSET_X = 23, SPELL_BUTTON_INSET_Y = 44;
|
||||
/** The distance between adjacent spell buttons (in both x and y). */
|
||||
private static final int SPELL_BUTTON_SPACING = 38;
|
||||
|
||||
private static final int SPELL_ROWS = 3, SPELL_COLUMNS = 3;
|
||||
public static final int SPELL_BUTTON_COUNT = SPELL_ROWS * SPELL_COLUMNS * 2; // x2 because there are 2 pages
|
||||
|
||||
private static final int SEARCH_TOOLTIP_HOVER_TIME = 20;
|
||||
|
||||
private static final Style TOOLTIP_SYNTAX = new Style().setColor(TextFormatting.YELLOW);
|
||||
private static final Style TOOLTIP_BODY = new Style().setColor(TextFormatting.WHITE);
|
||||
|
||||
private final TileEntityLectern lectern;
|
||||
|
||||
private GuiButton nextPageButton;
|
||||
private GuiButton prevPageButton;
|
||||
private GuiButton lastPageButton;
|
||||
private GuiButton firstPageButton;
|
||||
private GuiButton indexButton;
|
||||
private GuiButton locateButton;
|
||||
|
||||
private GuiButton[] sortButtons = new GuiButton[3];
|
||||
private GuiButtonSpell[] spellButtons = new GuiButtonSpell[SPELL_BUTTON_COUNT];
|
||||
|
||||
/** The spell currently being viewed, or null if the index is being viewed. */
|
||||
private Spell currentSpell;
|
||||
/** The available spells in nearby bookshelves; should not contain duplicates. */
|
||||
private List<Spell> availableSpells = new ArrayList<>();
|
||||
/** The spells matching the current search criteria, sorted according to the current sort settings. Will be a subset
|
||||
* of {@link GuiLectern#availableSpells}. */
|
||||
private List<Spell> matchingSpells;
|
||||
|
||||
private ISpellSortable.SortType sortType = ISpellSortable.SortType.TIER;
|
||||
private boolean sortDescending = false;
|
||||
|
||||
private GuiTextField searchField;
|
||||
private boolean searchNeedsClearing;
|
||||
private int searchBarHoverTime;
|
||||
|
||||
private int currentPage = 0;
|
||||
|
||||
public GuiLectern(TileEntityLectern lectern){
|
||||
super(288, 180);
|
||||
this.lectern = lectern;
|
||||
this.currentSpell = lectern.currentSpell;
|
||||
this.setTextureSize(512, 512);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spell getSpell(){
|
||||
return currentSpell;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTexture(){
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortType getSortType(){
|
||||
return sortType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSortDescending(){
|
||||
return sortDescending;
|
||||
}
|
||||
|
||||
private int getPageCount(){
|
||||
return MathHelper.ceil((float)matchingSpells.size() / SPELL_BUTTON_COUNT);
|
||||
}
|
||||
|
||||
private Spell getSpellForButton(GuiButtonSpell button){
|
||||
return matchingSpells.get(currentPage * SPELL_BUTTON_COUNT + button.index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui(){
|
||||
|
||||
super.initGui();
|
||||
|
||||
final int left = this.width / 2 - this.xSize / 2;
|
||||
final int top = this.height / 2 - this.ySize / 2;
|
||||
|
||||
int buttonID = 0;
|
||||
|
||||
// Page buttons
|
||||
this.buttonList.add(nextPageButton = new GuiButtonTurnPage(buttonID++, left + xSize - PAGE_BUTTON_INSET_X - GuiButtonTurnPage.WIDTH,
|
||||
top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_PAGE, TEXTURE, textureWidth, textureHeight));
|
||||
|
||||
this.buttonList.add(prevPageButton = new GuiButtonTurnPage(buttonID++, left + PAGE_BUTTON_INSET_X,
|
||||
top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_PAGE, TEXTURE, textureWidth, textureHeight));
|
||||
|
||||
this.buttonList.add(lastPageButton = new GuiButtonTurnPage(buttonID++, left + xSize - PAGE_BUTTON_INSET_X - GuiButtonTurnPage.WIDTH - PAGE_BUTTON_SPACING,
|
||||
top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_SECTION, TEXTURE, textureWidth, textureHeight));
|
||||
|
||||
this.buttonList.add(firstPageButton = new GuiButtonTurnPage(buttonID++, left + PAGE_BUTTON_INSET_X + PAGE_BUTTON_SPACING,
|
||||
top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_SECTION, TEXTURE, textureWidth, textureHeight));
|
||||
|
||||
this.buttonList.add(indexButton = new GuiButtonTurnPage(buttonID++, left + xSize/2 - 23,
|
||||
top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.CONTENTS, TEXTURE, textureWidth, textureHeight));
|
||||
|
||||
this.buttonList.add(locateButton = new GuiButtonLocateBook(buttonID++, left + xSize/2 - 34,
|
||||
top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT));
|
||||
|
||||
// Sort buttons
|
||||
for(SortType sortType : SortType.values()){
|
||||
this.buttonList.add(sortButtons[sortType.ordinal()] = new GuiButtonSpellSort(buttonID++,
|
||||
left + SORT_BUTTON_INSET_X + SORT_BUTTON_SPACING * sortType.ordinal(),
|
||||
top + SORT_BUTTON_INSET_Y, sortType, this, this));
|
||||
}
|
||||
|
||||
// Spell buttons
|
||||
for(int i = 0; i < SPELL_BUTTON_COUNT; i++){
|
||||
|
||||
int row = i % SPELL_COLUMNS;
|
||||
int column = (i / SPELL_COLUMNS) % SPELL_ROWS;
|
||||
|
||||
int x = i < SPELL_BUTTON_COUNT/2 ? SPELL_BUTTON_INSET_X + row * SPELL_BUTTON_SPACING
|
||||
: xSize - SPELL_BUTTON_INSET_X - GuiButtonSpell.WIDTH - (2-row) * SPELL_BUTTON_SPACING;
|
||||
int y = SPELL_BUTTON_INSET_Y + column * SPELL_BUTTON_SPACING;
|
||||
|
||||
this.buttonList.add(spellButtons[i] = new GuiButtonSpell(buttonID++, left + x, top + y, i));
|
||||
}
|
||||
|
||||
this.searchField = new GuiTextField(0, this.fontRenderer, left + 157, top + 21, 106, this.fontRenderer.FONT_HEIGHT);
|
||||
this.searchField.setMaxStringLength(50);
|
||||
this.searchField.setEnableBackgroundDrawing(false);
|
||||
this.searchField.setVisible(true);
|
||||
this.searchField.setTextColor(16777215);
|
||||
this.searchField.setCanLoseFocus(false);
|
||||
this.searchField.setFocused(true);
|
||||
|
||||
refreshAvailableSpells(); // Must be done last
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen(){
|
||||
super.updateScreen();
|
||||
if(searchBarHoverTime > 0 && searchBarHoverTime < SEARCH_TOOLTIP_HOVER_TIME) searchBarHoverTime++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed(){
|
||||
WizardryPacketHandler.net.sendToServer(new PacketLectern.Message(lectern.getPos(), currentSpell));
|
||||
super.onGuiClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackgroundLayer(int left, int top, int mouseX, int mouseY){
|
||||
if(currentSpell == Spells.none){
|
||||
drawIndexPage(left, top);
|
||||
}else{
|
||||
super.drawBackgroundLayer(left, top, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawForegroundLayer(int left, int top, int mouseX, int mouseY){
|
||||
|
||||
if(currentSpell == Spells.none){
|
||||
this.fontRenderer.drawString(I18n.format("gui." + Wizardry.MODID + ":lectern.title"),
|
||||
left + 20, top + SORT_BUTTON_INSET_Y, 0);
|
||||
}else{
|
||||
super.drawForegroundLayer(left, top, mouseX, mouseY);
|
||||
}
|
||||
|
||||
this.buttonList.forEach(b -> b.drawButtonForegroundLayer(mouseX, mouseY));
|
||||
|
||||
// Search tooltip
|
||||
if(DrawingUtils.isPointInRegion(searchField.x, searchField.y, searchField.width, searchField.height, mouseX, mouseY)){
|
||||
if(searchBarHoverTime == 0){
|
||||
searchBarHoverTime++;
|
||||
}else if(searchBarHoverTime == SEARCH_TOOLTIP_HOVER_TIME){
|
||||
drawHoveringText(I18n.format("container." + Wizardry.MODID + ":arcane_workbench.search_tooltip",
|
||||
TOOLTIP_SYNTAX.getFormattingCode(), TOOLTIP_BODY.getFormattingCode()), mouseX, mouseY);
|
||||
}
|
||||
}else{
|
||||
searchBarHoverTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void drawIndexPage(int left, int top){
|
||||
|
||||
for(int i = 0; i < SPELL_BUTTON_COUNT; i++){
|
||||
|
||||
int index = currentPage * SPELL_BUTTON_COUNT + i;
|
||||
Spell spell = index < matchingSpells.size() ? matchingSpells.get(index) : Spells.none;
|
||||
boolean discovered = Wizardry.proxy.shouldDisplayDiscovered(spell, null);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon());
|
||||
|
||||
int row = i % SPELL_COLUMNS;
|
||||
int column = (i / SPELL_COLUMNS) % SPELL_ROWS;
|
||||
|
||||
int x = i < SPELL_BUTTON_COUNT/2 ? SPELL_BUTTON_INSET_X + row * SPELL_BUTTON_SPACING
|
||||
: xSize - SPELL_BUTTON_INSET_X - GuiButtonSpell.WIDTH - (2-row) * SPELL_BUTTON_SPACING;
|
||||
int y = SPELL_BUTTON_INSET_Y + column * SPELL_BUTTON_SPACING;
|
||||
|
||||
DrawingUtils.drawTexturedRect(left + x + 1, top + y + 1, 0, 0, 32, 32, 32, 32);
|
||||
}
|
||||
|
||||
mc.renderEngine.bindTexture(getTexture());
|
||||
DrawingUtils.drawTexturedRect(left, top, 0, 256, xSize, ySize, textureWidth, textureHeight);
|
||||
|
||||
this.searchField.drawTextBox();
|
||||
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
mc.renderEngine.bindTexture(getTexture());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
searchNeedsClearing = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button){
|
||||
|
||||
int lastPage = getPageCount() - 1;
|
||||
|
||||
if(button == indexButton){
|
||||
currentSpell = Spells.none;
|
||||
// currentPage = 0;
|
||||
|
||||
}else if(button == locateButton){
|
||||
// Close the GUI
|
||||
this.mc.player.connection.sendPacket(new CPacketCloseWindow(this.mc.player.openContainer.windowId));
|
||||
this.mc.displayGuiScreen(null);
|
||||
|
||||
// Find the location(s) of the current spell's book(s) and highlight them
|
||||
for(IInventory bookshelf : BlockBookshelf.findNearbyBookshelves(lectern.getWorld(), lectern.getPos())){
|
||||
|
||||
for(int i = 0; i < bookshelf.getSizeInventory(); i++){
|
||||
|
||||
ItemStack stack = bookshelf.getStackInSlot(i);
|
||||
|
||||
if(stack.getItem() instanceof ItemSpellBook){
|
||||
|
||||
Spell spell = Spell.byMetadata(stack.getMetadata());
|
||||
|
||||
if(spell == this.currentSpell){
|
||||
|
||||
BlockPos pos = (((TileEntity)bookshelf).getPos());
|
||||
|
||||
for(EnumFacing side : EnumFacing.VALUES){
|
||||
ParticleBuilder.create(ParticleBuilder.Type.BLOCK_HIGHLIGHT).pos(
|
||||
GeometryUtils.getFaceCentre(pos, side)
|
||||
.add(new Vec3d(side.getDirectionVec())
|
||||
.scale(GeometryUtils.ANTI_Z_FIGHTING_OFFSET)))
|
||||
.face(side).clr(0.9f, 0.5f, 0.8f).fade(0.7f, 0, 1).spawn(mc.world);
|
||||
}
|
||||
|
||||
mc.world.playSound(pos, WizardrySounds.BLOCK_LECTERN_LOCATE_SPELL, SoundCategory.BLOCKS, 1, 0.7f, false);
|
||||
|
||||
break; // This bookshelf has the spell, skip to the next bookshelf
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else if(button == nextPageButton){
|
||||
if(currentPage < lastPage) currentPage++;
|
||||
|
||||
}else if(button == prevPageButton){
|
||||
if(currentPage > 0) currentPage--;
|
||||
|
||||
}else if(button == lastPageButton){
|
||||
currentPage = lastPage;
|
||||
|
||||
}else if(button == firstPageButton){
|
||||
currentPage = 0;
|
||||
|
||||
}else if(button instanceof GuiButtonSpell){
|
||||
currentSpell = getSpellForButton((GuiButtonSpell)button);
|
||||
|
||||
}else if(button instanceof GuiButtonSpellSort){
|
||||
|
||||
SortType sortType = (((GuiButtonSpellSort)button).sortType);
|
||||
|
||||
if(this.sortType == sortType){
|
||||
this.sortDescending = !this.sortDescending;
|
||||
}else{
|
||||
this.sortType = sortType;
|
||||
this.sortDescending = false;
|
||||
}
|
||||
|
||||
updateMatchingSpells();
|
||||
}
|
||||
|
||||
updateButtonVisiblity();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(char typedChar, int keyCode) throws IOException {
|
||||
|
||||
if(this.searchNeedsClearing){
|
||||
this.searchNeedsClearing = false;
|
||||
this.searchField.setText("");
|
||||
this.currentPage = 0;
|
||||
}
|
||||
|
||||
if(this.searchField.textboxKeyTyped(typedChar, keyCode)){
|
||||
this.currentPage = 0;
|
||||
updateMatchingSpells();
|
||||
updateButtonVisiblity();
|
||||
}else{
|
||||
super.keyTyped(typedChar, keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateButtonVisiblity(){
|
||||
|
||||
if(currentSpell == Spells.none){
|
||||
|
||||
this.searchField.setVisible(true);
|
||||
|
||||
int lastPage = getPageCount() - 1;
|
||||
|
||||
prevPageButton.visible = currentPage > 0;
|
||||
firstPageButton.visible = currentPage > 0;
|
||||
nextPageButton.visible = currentPage < lastPage;
|
||||
lastPageButton.visible = currentPage < lastPage;
|
||||
|
||||
indexButton.visible = false;
|
||||
locateButton.visible = false;
|
||||
|
||||
for(GuiButton button : sortButtons) button.visible = true;
|
||||
|
||||
for(GuiButtonSpell button : spellButtons){
|
||||
button.visible = currentPage * SPELL_BUTTON_COUNT + button.index < matchingSpells.size();
|
||||
}
|
||||
|
||||
}else{
|
||||
this.searchField.setVisible(false);
|
||||
this.buttonList.forEach(b -> b.visible = false); // Hide all buttons...
|
||||
indexButton.visible = true; // ... except the index button and locate button
|
||||
locateButton.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMatchingSpells(){
|
||||
matchingSpells = availableSpells.stream()
|
||||
.filter(s -> s.matches(searchField.getText().toLowerCase(Locale.ROOT)))
|
||||
.sorted(sortDescending ? sortType.comparator.reversed() : sortType.comparator)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// TODO: Config option to always display all spells when in creative
|
||||
/** Called on initialisation and whenever a bookshelf is added or removed, to update the list of spells. */
|
||||
public void refreshAvailableSpells(){
|
||||
|
||||
availableSpells.clear();
|
||||
|
||||
// No need to exclude the lectern TE because it's not an IInventory!
|
||||
for(IInventory bookshelf : BlockBookshelf.findNearbyBookshelves(lectern.getWorld(), lectern.getPos())){
|
||||
|
||||
for(int i=0; i<bookshelf.getSizeInventory(); i++){
|
||||
|
||||
ItemStack stack = bookshelf.getStackInSlot(i);
|
||||
|
||||
if(stack.getItem() instanceof ItemSpellBook){
|
||||
Spell spell = Spell.byMetadata(stack.getMetadata());
|
||||
if(spell != Spells.none && !availableSpells.contains(spell)) availableSpells.add(spell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!availableSpells.contains(currentSpell)) currentSpell = Spells.none;
|
||||
|
||||
updateMatchingSpells();
|
||||
updateButtonVisiblity();
|
||||
|
||||
}
|
||||
|
||||
private class GuiButtonLocateBook extends GuiButton {
|
||||
|
||||
public GuiButtonLocateBook(int id, int x, int y){
|
||||
super(id, x, y, 12, 12, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
|
||||
|
||||
if(this.visible){
|
||||
|
||||
boolean flag = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
minecraft.getTextureManager().bindTexture(TEXTURE);
|
||||
|
||||
DrawingUtils.drawTexturedRect(this.x, this.y, flag ? width : 0, 184, width, height, textureWidth, textureHeight);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class GuiButtonSpell extends GuiButtonInvisible {
|
||||
|
||||
private static final int WIDTH = 34, HEIGHT = 34;
|
||||
|
||||
private final int index;
|
||||
|
||||
public GuiButtonSpell(int id, int x, int y, int index){
|
||||
super(id, x, y, WIDTH, HEIGHT);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playPressSound(SoundHandler soundHandler){
|
||||
soundHandler.playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_PAGE_TURN, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
|
||||
if(visible){
|
||||
super.drawButton(minecraft, mouseX, mouseY, partialTicks);
|
||||
if(hovered){
|
||||
mc.renderEngine.bindTexture(getTexture());
|
||||
DrawingUtils.drawTexturedRect(x, y, 40, 180, width, height, textureWidth, textureHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawButtonForegroundLayer(int mouseX, int mouseY){
|
||||
if(visible && hovered){
|
||||
Spell spell = getSpellForButton(this);
|
||||
if(Wizardry.proxy.shouldDisplayDiscovered(spell, null)){
|
||||
drawHoveringText(Collections.singletonList(spell.getDisplayName()), mouseX, mouseY, fontRenderer);
|
||||
}else{
|
||||
drawHoveringText(Collections.singletonList(SpellGlyphData.getGlyphName(spell, mc.world)),
|
||||
mouseX, mouseY, mc.standardGalacticFontRenderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,113 +1,35 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.constants.Tier;
|
||||
import electroblob.wizardry.data.SpellGlyphData;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.item.ItemSpellBook;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class GuiSpellBook extends GuiScreen {
|
||||
public class GuiSpellBook extends GuiSpellInfo {
|
||||
|
||||
private int xSize, ySize;
|
||||
private ItemSpellBook book;
|
||||
private Spell spell;
|
||||
private final ItemSpellBook book;
|
||||
private final Spell spell;
|
||||
|
||||
public GuiSpellBook(ItemStack stack){
|
||||
super();
|
||||
xSize = 288;
|
||||
ySize = 180;
|
||||
if(!(stack.getItem() instanceof ItemSpellBook)) throw new ClassCastException("Cannot create spell book GUI for item that does not extend ItemSpellBook!");
|
||||
|
||||
super(288, 180);
|
||||
|
||||
if(!(stack.getItem() instanceof ItemSpellBook)){
|
||||
throw new ClassCastException("Cannot create spell book GUI for item that does not extend ItemSpellBook!");
|
||||
}
|
||||
|
||||
this.book = (ItemSpellBook)stack.getItem();
|
||||
this.spell = Spell.byMetadata(stack.getItemDamage());
|
||||
this.spell = (Spell.byMetadata(stack.getItemDamage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int par1, int par2, float par3){
|
||||
|
||||
int xPos = this.width / 2 - xSize / 2;
|
||||
int yPos = this.height / 2 - this.ySize / 2;
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
|
||||
boolean discovered = true;
|
||||
if(Wizardry.settings.discoveryMode && !player.isCreative() && WizardData.get(player) != null
|
||||
&& !WizardData.get(player).hasSpellBeenDiscovered(spell)){
|
||||
discovered = false;
|
||||
}
|
||||
|
||||
GlStateManager.color(1, 1, 1, 1); // Just in case
|
||||
|
||||
// Draws spell illustration on opposite page, underneath the book so it shows through the hole.
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon());
|
||||
DrawingUtils.drawTexturedRect(xPos + 146, yPos + 20, 0, 0, 128, 128, 128, 128);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(book.getGuiTexture(spell));
|
||||
DrawingUtils.drawTexturedRect(xPos, yPos, 0, 0, xSize, ySize, xSize, 256);
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
|
||||
if(discovered){
|
||||
this.fontRenderer.drawString(spell.getDisplayName(), xPos + 17, yPos + 15, 0);
|
||||
this.fontRenderer.drawString(spell.getType().getDisplayName(), xPos + 17, yPos + 26, 0x777777);
|
||||
}else{
|
||||
this.mc.standardGalacticFontRenderer.drawString(SpellGlyphData.getGlyphName(spell, player.world), xPos + 17,
|
||||
yPos + 15, 0);
|
||||
this.mc.standardGalacticFontRenderer.drawString(spell.getType().getDisplayName(), xPos + 17, yPos + 26,
|
||||
0x777777);
|
||||
}
|
||||
|
||||
// Novice is usually white but this doesn't show up
|
||||
String tier = I18n.format("gui.ebwizardry:spell_book.tier", spell.getTier() == Tier.NOVICE ?
|
||||
"\u00A77" + spell.getTier().getDisplayName() : spell.getTier().getDisplayNameWithFormatting());
|
||||
this.fontRenderer.drawString(tier, xPos + 17, yPos + 45, 0);
|
||||
|
||||
String element = I18n.format("gui.ebwizardry:spell_book.element", spell.getElement().getFormattingCode() + spell.getElement().getDisplayName());
|
||||
if(!discovered) element = I18n.format("gui.ebwizardry:spell_book.element_undiscovered");
|
||||
this.fontRenderer.drawString(element, xPos + 17, yPos + 57, 0);
|
||||
|
||||
String manaCost = I18n.format("gui.ebwizardry:spell_book.mana_cost", spell.getCost());
|
||||
if(spell.isContinuous) manaCost = I18n.format("gui.ebwizardry:spell_book.mana_cost_continuous", spell.getCost());
|
||||
if(!discovered) manaCost = I18n.format("gui.ebwizardry:spell_book.mana_cost_undiscovered");
|
||||
this.fontRenderer.drawString(manaCost, xPos + 17, yPos + 69, 0);
|
||||
|
||||
if(discovered){
|
||||
this.fontRenderer.drawSplitString(spell.getDescription(), xPos + 17, yPos + 83, 118, 0);
|
||||
}else{
|
||||
this.mc.standardGalacticFontRenderer.drawSplitString(
|
||||
SpellGlyphData.getGlyphDescription(spell, player.world), xPos + 17, yPos + 83, 118, 0);
|
||||
}
|
||||
public Spell getSpell(){
|
||||
return spell;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui(){
|
||||
super.initGui();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
this.buttonList.clear();
|
||||
|
||||
this.mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_BOOK_OPEN, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed(){
|
||||
super.onGuiClosed();
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesGuiPauseGame(){
|
||||
return Wizardry.settings.booksPauseGame;
|
||||
public ResourceLocation getTexture(){
|
||||
return book.getGuiTexture(spell);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import electroblob.wizardry.item.ISpellCastingItem;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.WandHelper;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -45,7 +45,8 @@ import java.nio.charset.StandardCharsets;
|
||||
public class GuiSpellDisplay {
|
||||
|
||||
private static final ResourceLocation INDEX = new ResourceLocation(Wizardry.MODID, "textures/gui/spell_hud/_index.json");
|
||||
|
||||
private static final ResourceLocation CHARGE_METER = new ResourceLocation(Wizardry.MODID, "textures/gui/spell_charge_meter.png");
|
||||
|
||||
/** A map which stores all loaded HUD skin objects. This gets wiped on resource pack reload and repopulated with
|
||||
* mappings as specified by {@code _index.json} (these stack between resource packs). The keys in the map correspond
|
||||
* to the keys in {@code _index.json}, and are sorted in that order, with skins belonging to resource packs sorted
|
||||
@@ -54,6 +55,12 @@ public class GuiSpellDisplay {
|
||||
private static final Map<String, Skin> skins = new LinkedHashMap<>(14); // 14 is the number of skins packaged with the mod
|
||||
|
||||
private static final Gson gson = new Gson();
|
||||
private static final Random random = new Random();
|
||||
|
||||
/** Width of the charge meter. */
|
||||
private static final int CHARGE_METER_WIDTH = 25;
|
||||
/** Height of the charge meter. */
|
||||
private static final int CHARGE_METER_HEIGHT = 9;
|
||||
|
||||
/** Width and height of the spell icon (very unlikely to change!) */
|
||||
private static final int SPELL_ICON_SIZE = 32;
|
||||
@@ -99,12 +106,9 @@ public class GuiSpellDisplay {
|
||||
@SubscribeEvent
|
||||
public static void draw(RenderGameOverlayEvent.Post event){
|
||||
|
||||
if(event.getType() != RenderGameOverlayEvent.ElementType.TEXT
|
||||
&& event.getType() != RenderGameOverlayEvent.ElementType.HOTBAR) return;
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if(!Wizardry.settings.showSpellHUD && !Wizardry.settings.showChargeMeter) return; // Optimisation
|
||||
|
||||
EntityPlayer player = mc.player;
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
|
||||
if(player.isSpectator()) return; // Spectators shouldn't have the spell HUD!
|
||||
|
||||
@@ -117,12 +121,89 @@ public class GuiSpellDisplay {
|
||||
wand = player.getHeldItemOffhand();
|
||||
mainHand = false;
|
||||
// If the player isn't holding a spellcasting item that shows the HUD, then nothing else needs to be done.
|
||||
if(!(wand.getItem() instanceof ISpellCastingItem && ((ISpellCastingItem)wand.getItem()).showSpellHUD(player, wand))) return;
|
||||
if(!(wand.getItem() instanceof ISpellCastingItem && ((ISpellCastingItem)wand.getItem()).showSpellHUD(player, wand)))
|
||||
return;
|
||||
}
|
||||
|
||||
int width = event.getResolution().getScaledWidth();
|
||||
int height = event.getResolution().getScaledHeight();
|
||||
|
||||
switch(event.getType()){
|
||||
case CROSSHAIRS:
|
||||
renderChargeMeter(player, wand, width, height, event.getPartialTicks());
|
||||
break;
|
||||
case HOTBAR:
|
||||
renderSpellHUD(player, wand, mainHand, width, height, event.getPartialTicks(), false);
|
||||
break;
|
||||
case TEXT:
|
||||
renderSpellHUD(player, wand, mainHand, width, height, event.getPartialTicks(), true);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the spell charge meter around the crosshairs.
|
||||
* @param player A reference to the client player
|
||||
* @param wand The wand the HUD is for
|
||||
* @param width The width of the screen
|
||||
* @param height The height of the screen
|
||||
* @param partialTicks The current partial tick time
|
||||
*/
|
||||
private static void renderChargeMeter(EntityPlayer player, ItemStack wand, int width, int height, float partialTicks){
|
||||
|
||||
if(!Wizardry.settings.showChargeMeter) return;
|
||||
if(Minecraft.getMinecraft().gameSettings.showDebugInfo) return; // Don't show charge meter in the debug screen
|
||||
if(Minecraft.getMinecraft().gameSettings.thirdPersonView != 0) return; // Don't show in third person
|
||||
if(wand != player.getActiveItemStack()) return; // Don't show when using the other held item
|
||||
|
||||
if(!(wand.getItem() instanceof ISpellCastingItem)) throw new IllegalArgumentException("The given stack must contain an ISpellCastingItem!");
|
||||
|
||||
Spell spell = ((ISpellCastingItem)wand.getItem()).getCurrentSpell(wand);
|
||||
|
||||
int chargeup = spell.getChargeup();
|
||||
|
||||
if(WizardData.get(player) != null){
|
||||
// Pretty sure this is accessible client-side since it's only assigned from common code
|
||||
chargeup = (int)(chargeup * WizardData.get(player).itemCastingModifiers.get(SpellModifiers.CHARGEUP));
|
||||
}
|
||||
|
||||
if(chargeup <= 0) return;
|
||||
|
||||
// WHY WHY WHY are these methods named so misleadingly?! Sort yourselves out MCP!
|
||||
// (getItemInUseCount returns the max count MINUS the use count, and getItemInUseMaxCount returns the use count)
|
||||
if(player.getItemInUseMaxCount() == 0) return; // Not charging
|
||||
float charge = (player.getItemInUseMaxCount() + partialTicks) / chargeup;
|
||||
if(charge > 1) return; // Done charging
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(CHARGE_METER);
|
||||
|
||||
int x1 = width/2 - CHARGE_METER_WIDTH/2;
|
||||
int y = height/2 - CHARGE_METER_HEIGHT/2;
|
||||
int w = (int)(CHARGE_METER_WIDTH/2 * charge);
|
||||
int u = CHARGE_METER_WIDTH - w;
|
||||
|
||||
DrawingUtils.drawTexturedRect(x1, y, 0, 0, w, CHARGE_METER_HEIGHT, 32, 32);
|
||||
DrawingUtils.drawTexturedRect(x1 + u, y, u, 0, w, CHARGE_METER_HEIGHT, 32, 32);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the main spell HUD in the corner of the screen.
|
||||
* @param player A reference to the client player
|
||||
* @param wand The wand the HUD is for
|
||||
* @param mainHand True if the wand is in the player's main hand, false if it is in their offhand
|
||||
* @param width The width of the screen
|
||||
* @param height The height of the screen
|
||||
* @param partialTicks The current partial tick time
|
||||
* @param textLayer True to render the text layer, false to render the background (hotbar layer)
|
||||
*/
|
||||
private static void renderSpellHUD(EntityPlayer player, ItemStack wand, boolean mainHand, int width, int height, float partialTicks, boolean textLayer){
|
||||
|
||||
if(!Wizardry.settings.showSpellHUD) return;
|
||||
|
||||
if(!(wand.getItem() instanceof ISpellCastingItem)) throw new IllegalArgumentException("The given stack must contain an ISpellCastingItem!");
|
||||
|
||||
boolean flipX = Wizardry.settings.spellHUDPosition.flipX;
|
||||
boolean flipY = Wizardry.settings.spellHUDPosition.flipY;
|
||||
|
||||
@@ -130,16 +211,16 @@ public class GuiSpellDisplay {
|
||||
// ............. | This bit is true if the wand is on the left, false if it is on the right
|
||||
flipX = flipX == ((mainHand ? player.getPrimaryHand() : player.getPrimaryHand().opposite()) == EnumHandSide.LEFT);
|
||||
}
|
||||
|
||||
|
||||
Skin skin = skins.get(Wizardry.settings.spellHUDSkin);
|
||||
|
||||
|
||||
if(skin == null){
|
||||
|
||||
|
||||
Wizardry.logger.info("The spell HUD skin '" + Wizardry.settings.spellHUDSkin + "' specified in the config"
|
||||
+ " did not match any of the loaded skins; using the default skin as a fallback.");
|
||||
|
||||
|
||||
skin = skins.get(Settings.DEFAULT_HUD_SKIN_KEY);
|
||||
|
||||
|
||||
if(skin == null){
|
||||
Wizardry.logger.warn("The default spell HUD skin is missing! A resource pack must have overridden it"
|
||||
+ " with an invalid JSON file (default.json), please try again without any resource packs.");
|
||||
@@ -148,7 +229,7 @@ public class GuiSpellDisplay {
|
||||
}
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
|
||||
// 'Origin' of the spell hud (bottom left corner of the actual texture, always in the corner of the screen)
|
||||
int x = flipX ? width : 0;
|
||||
int y = flipY ? 0: height;
|
||||
@@ -169,45 +250,45 @@ public class GuiSpellDisplay {
|
||||
y = MathHelper.ceil(y/scale);
|
||||
}
|
||||
|
||||
Spell spell = WandHelper.getCurrentSpell(wand);
|
||||
int cooldown = WandHelper.getCurrentCooldown(wand);
|
||||
int maxCooldown = WandHelper.getCurrentMaxCooldown(wand);
|
||||
Spell spell = ((ISpellCastingItem)wand.getItem()).getCurrentSpell(wand);
|
||||
int cooldown = ((ISpellCastingItem)wand.getItem()).getCurrentCooldown(wand);
|
||||
int maxCooldown = ((ISpellCastingItem)wand.getItem()).getCurrentMaxCooldown(wand);
|
||||
|
||||
if(textLayer){
|
||||
|
||||
if(event.getType() == RenderGameOverlayEvent.ElementType.TEXT){
|
||||
|
||||
float animationProgress = Math.signum(switchTimer) * ((SPELL_SWITCH_TIME - Math.abs(switchTimer) +
|
||||
event.getPartialTicks()) / SPELL_SWITCH_TIME);
|
||||
|
||||
String prevSpellName = getFormattedSpellName(WandHelper.getPreviousSpell(wand), player, WandHelper.getPreviousCooldown(wand));
|
||||
partialTicks) / SPELL_SWITCH_TIME);
|
||||
|
||||
String prevSpellName = getFormattedSpellName(((ISpellCastingItem)wand.getItem()).getPreviousSpell(wand), player, 0);
|
||||
String spellName = getFormattedSpellName(spell, player, cooldown);
|
||||
String nextSpellName = getFormattedSpellName(WandHelper.getNextSpell(wand), player, WandHelper.getNextCooldown(wand));
|
||||
String nextSpellName = getFormattedSpellName(((ISpellCastingItem)wand.getItem()).getNextSpell(wand), player, 0);
|
||||
|
||||
skin.drawText(x, y, flipX, flipY, prevSpellName, spellName, nextSpellName, animationProgress);
|
||||
|
||||
}else if(event.getType() == RenderGameOverlayEvent.ElementType.HOTBAR){
|
||||
}else{
|
||||
|
||||
boolean discovered = true;
|
||||
|
||||
if(!player.isCreative() && WizardData.get(player) != null){
|
||||
discovered = WizardData.get(player).hasSpellBeenDiscovered(spell);
|
||||
}
|
||||
|
||||
|
||||
ResourceLocation icon = discovered ? spell.getIcon() : Spells.none.getIcon();
|
||||
|
||||
float progress = 1;
|
||||
// Doesn't really matter what progress is when in creative, but we might as well avoid the calculation.
|
||||
if(!player.isCreative() && !spell.isContinuous){
|
||||
if(!player.isCreative()){
|
||||
// Subtracted partial tick time to make it smoother
|
||||
progress = maxCooldown == 0 ? 1 : (maxCooldown - (float)cooldown + event.getPartialTicks()) / maxCooldown;
|
||||
progress = maxCooldown == 0 ? 1 : (maxCooldown - (float)cooldown + partialTicks) / maxCooldown;
|
||||
}
|
||||
|
||||
skin.drawBackground(x, y, flipX, flipY, icon, progress, player.isCreative());
|
||||
|
||||
|
||||
skin.drawBackground(x, y, flipX, flipY, icon, progress, player.isCreative(), player.isPotionActive(WizardryPotions.arcane_jammer));
|
||||
|
||||
}
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the name of the given spell, with formatting added according to its cooldown and whether the given player
|
||||
* has discovered it.
|
||||
@@ -224,9 +305,11 @@ public class GuiSpellDisplay {
|
||||
discovered = WizardData.get(player).hasSpellBeenDiscovered(spell);
|
||||
}
|
||||
|
||||
// Makes spells greyed out if they are in cooldown or if the player has the arcane jammer effect
|
||||
String format = cooldown > 0 || player.isPotionActive(WizardryPotions.arcane_jammer) ? "\u00A78" : spell.getElement().getFormattingCode();
|
||||
// Makes spells greyed out if they are in cooldown
|
||||
String format = cooldown > 0 ? "\u00A78" : spell.getElement().getFormattingCode();
|
||||
if(!discovered) format = "\u00A79";
|
||||
// Obfuscates the spell name if the player has the arcane jammer effect
|
||||
if(player.isPotionActive(WizardryPotions.arcane_jammer)) format = format + "\u00A7k";
|
||||
|
||||
String name = discovered ? spell.getDisplayName() : SpellGlyphData.getGlyphName(spell, player.world);
|
||||
name = format + name;
|
||||
@@ -458,8 +541,9 @@ public class GuiSpellDisplay {
|
||||
* @param icon A {@code ResourceLocation} corresponding to the icon of the selected spell.
|
||||
* @param cooldownBarProgress The fraction of the cooldown bar to draw; must be between 0 and 1 (inclusive).
|
||||
* @param creativeMode True to draw the creative mode HUD, false for the survival mode version.
|
||||
* @param jammed True to show the 'glitch' effect (user for arcane jammer), false to draw normally.
|
||||
*/
|
||||
public void drawBackground(int x, int y, boolean flipX, boolean flipY, ResourceLocation icon, float cooldownBarProgress, boolean creativeMode){
|
||||
public void drawBackground(int x, int y, boolean flipX, boolean flipY, ResourceLocation icon, float cooldownBarProgress, boolean creativeMode, boolean jammed){
|
||||
|
||||
// Moves the origin if the HUD does not mirror; neatens the rest of the code.
|
||||
if(flipX && !mirrorX) x -= width;
|
||||
@@ -476,8 +560,13 @@ public class GuiSpellDisplay {
|
||||
int x1 = flipX && mirrorX ? x - spellIconInsetX - SPELL_ICON_SIZE : x + spellIconInsetX;
|
||||
// y is upside-down so this is the other way round
|
||||
int y1 = flipY && mirrorY ? y + spellIconInsetY : y - spellIconInsetY - SPELL_ICON_SIZE;
|
||||
|
||||
DrawingUtils.drawTexturedRect(x1, y1, 0, 0, SPELL_ICON_SIZE, SPELL_ICON_SIZE, SPELL_ICON_SIZE, SPELL_ICON_SIZE);
|
||||
|
||||
if(jammed){
|
||||
random.setSeed(Minecraft.getMinecraft().world.getTotalWorldTime() / 2);
|
||||
DrawingUtils.drawGlitchRect(random, x1, y1, 0, 0, SPELL_ICON_SIZE, SPELL_ICON_SIZE, SPELL_ICON_SIZE, SPELL_ICON_SIZE, false, false);
|
||||
}else{
|
||||
DrawingUtils.drawTexturedRect(x1, y1, 0, 0, SPELL_ICON_SIZE, SPELL_ICON_SIZE, SPELL_ICON_SIZE, SPELL_ICON_SIZE);
|
||||
}
|
||||
|
||||
// Background of spell hud
|
||||
mc.renderEngine.bindTexture(texture);
|
||||
@@ -486,7 +575,11 @@ public class GuiSpellDisplay {
|
||||
y1 = flipY && mirrorY ? y : y - height;
|
||||
// The 128 here is a uv value, not a dimension, and hence is left as a hardcoded number.
|
||||
// TODO: Since the HUD is wider than it is tall, perhaps the creative mode texture should be in the bottom half instead of the right half?
|
||||
DrawingUtils.drawTexturedFlippedRect(x1, y1, creativeMode ? 128 : 0, 0, width, height, 256, 256, flipX && mirrorX, flipY && mirrorY);
|
||||
if(jammed){
|
||||
DrawingUtils.drawGlitchRect(random, x1, y1, creativeMode ? 128 : 0, 0, width, height, 256, 256, flipX && mirrorX, flipY && mirrorY);
|
||||
}else{
|
||||
DrawingUtils.drawTexturedFlippedRect(x1, y1, creativeMode ? 128 : 0, 0, width, height, 256, 256, flipX && mirrorX, flipY && mirrorY);
|
||||
}
|
||||
|
||||
// Cooldown bar
|
||||
if(!creativeMode && cooldownBarProgress > 0 && (showCooldownWhenFull || cooldownBarProgress < 1)){
|
||||
@@ -498,8 +591,12 @@ public class GuiSpellDisplay {
|
||||
|
||||
int u = cooldownBarX; // This doesn't change, even when cooldownBarMirrorX is true, because it should
|
||||
int v = height; // always start with the left-hand in the actual texture file
|
||||
|
||||
DrawingUtils.drawTexturedFlippedRect(x1, y1, u, v, l, cooldownBarHeight, 256, 256, flipX && cooldownBarMirrorX, flipY && cooldownBarMirrorY);
|
||||
|
||||
if(jammed){
|
||||
DrawingUtils.drawGlitchRect(random, x1, y1, u, v, l, cooldownBarHeight, 256, 256, flipX && cooldownBarMirrorX, flipY && cooldownBarMirrorY);
|
||||
}else{
|
||||
DrawingUtils.drawTexturedFlippedRect(x1, y1, u, v, l, cooldownBarHeight, 256, 256, flipX && cooldownBarMirrorX, flipY && cooldownBarMirrorY);
|
||||
}
|
||||
}
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.constants.Tier;
|
||||
import electroblob.wizardry.data.SpellGlyphData;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
/** Abstract base class for both {@link GuiSpellBook} and {@link GuiLectern}. Centralises code common to both
|
||||
* those classes. */
|
||||
public abstract class GuiSpellInfo extends GuiScreen {
|
||||
|
||||
protected static final String TRANSLATION_KEY_PREFIX = "gui." + Wizardry.MODID + ":spell_book";
|
||||
|
||||
protected final int xSize, ySize;
|
||||
protected int textureWidth = 512;
|
||||
protected int textureHeight = 256;
|
||||
|
||||
public GuiSpellInfo(int xSize, int ySize){
|
||||
super();
|
||||
this.xSize = xSize;
|
||||
this.ySize = ySize;
|
||||
}
|
||||
|
||||
protected void setTextureSize(int width, int height){
|
||||
this.textureWidth = width;
|
||||
this.textureHeight = height;
|
||||
}
|
||||
|
||||
/** Returns the spell to be displayed by this GUI. */
|
||||
public abstract Spell getSpell();
|
||||
|
||||
/** Returns the main texture for the background of this GUI. */
|
||||
public abstract ResourceLocation getTexture();
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks){
|
||||
int left = this.width/2 - xSize/2;
|
||||
int top = this.height/2 - this.ySize/2;
|
||||
this.drawDefaultBackground();
|
||||
this.drawBackgroundLayer(left, top, mouseX, mouseY);
|
||||
super.drawScreen(mouseX, mouseY, partialTicks); // Just draws the buttons
|
||||
this.drawForegroundLayer(left, top, mouseX, mouseY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the background of the spell info GUI. This is called before buttons are drawn.
|
||||
* @param left The x-coordinate of the left-hand edge of the GUI
|
||||
* @param top The y-coordinate of the top edge of the GUI
|
||||
* @param mouseX The current x position of the mouse pointer
|
||||
* @param mouseY The current y position of the mouse pointer
|
||||
*/
|
||||
protected void drawBackgroundLayer(int left, int top, int mouseX, int mouseY){
|
||||
|
||||
boolean discovered = Wizardry.proxy.shouldDisplayDiscovered(getSpell(), null);
|
||||
|
||||
GlStateManager.color(1, 1, 1, 1); // Just in case
|
||||
|
||||
// Draws spell illustration on opposite page, underneath the book so it shows through the hole.
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? getSpell().getIcon() : Spells.none.getIcon());
|
||||
DrawingUtils.drawTexturedRect(left + 146, top + 20, 0, 0, 128, 128, 128, 128);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(getTexture());
|
||||
DrawingUtils.drawTexturedRect(left, top, 0, 0, xSize, ySize, textureWidth, textureHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the foreground of the spell info GUI. This is called after buttons are drawn.
|
||||
* @param left The x-coordinate of the left-hand edge of the GUI
|
||||
* @param top The y-coordinate of the top edge of the GUI
|
||||
* @param mouseX The current x position of the mouse pointer
|
||||
* @param mouseY The current y position of the mouse pointer
|
||||
*/
|
||||
protected void drawForegroundLayer(int left, int top, int mouseX, int mouseY){
|
||||
|
||||
boolean discovered = Wizardry.proxy.shouldDisplayDiscovered(getSpell(), null);
|
||||
|
||||
if(discovered){
|
||||
this.fontRenderer.drawString(getSpell().getDisplayName(), left + 17, top + 15, 0);
|
||||
this.fontRenderer.drawString(getSpell().getType().getDisplayName(), left + 17, top + 26, 0x777777);
|
||||
}else{
|
||||
this.mc.standardGalacticFontRenderer.drawString(SpellGlyphData.getGlyphName(getSpell(), mc.world), left + 17,
|
||||
top + 15, 0);
|
||||
this.mc.standardGalacticFontRenderer.drawString(getSpell().getType().getDisplayName(), left + 17, top + 26,
|
||||
0x777777);
|
||||
}
|
||||
|
||||
// Novice is usually white but this doesn't show up
|
||||
String tier = I18n.format(TRANSLATION_KEY_PREFIX + ".tier", getSpell().getTier() == Tier.NOVICE ?
|
||||
"\u00A77" + getSpell().getTier().getDisplayName() : getSpell().getTier().getDisplayNameWithFormatting());
|
||||
this.fontRenderer.drawString(tier, left + 17, top + 45, 0);
|
||||
|
||||
String element = I18n.format(TRANSLATION_KEY_PREFIX + ".element", getSpell().getElement().getFormattingCode() + getSpell().getElement().getDisplayName());
|
||||
if(!discovered) element = I18n.format(TRANSLATION_KEY_PREFIX + ".element_undiscovered");
|
||||
this.fontRenderer.drawString(element, left + 17, top + 57, 0);
|
||||
|
||||
String manaCost = I18n.format(TRANSLATION_KEY_PREFIX + ".mana_cost", getSpell().getCost());
|
||||
if(getSpell().isContinuous) manaCost = I18n.format(TRANSLATION_KEY_PREFIX + ".mana_cost_continuous", getSpell().getCost());
|
||||
if(!discovered) manaCost = I18n.format(TRANSLATION_KEY_PREFIX + ".mana_cost_undiscovered");
|
||||
this.fontRenderer.drawString(manaCost, left + 17, top + 69, 0);
|
||||
|
||||
if(discovered){
|
||||
this.fontRenderer.drawSplitString(getSpell().getDescription(), left + 17, top + 83, 118, 0);
|
||||
}else{
|
||||
this.mc.standardGalacticFontRenderer.drawSplitString(
|
||||
SpellGlyphData.getGlyphDescription(getSpell(), mc.world), left + 17, top + 83, 118, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui(){
|
||||
super.initGui();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
this.buttonList.clear();
|
||||
this.mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_BOOK_OPEN, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed(){
|
||||
super.onGuiClosed();
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesGuiPauseGame(){
|
||||
return Wizardry.settings.booksPauseGame;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.item.ItemSpellBook;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiMerchant;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.ContainerMerchant;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.village.MerchantRecipe;
|
||||
import net.minecraft.village.MerchantRecipeList;
|
||||
import net.minecraftforge.client.event.GuiContainerEvent;
|
||||
import net.minecraftforge.client.event.GuiOpenEvent;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent.ActionPerformedEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class WizardTradeTweaksHandler {
|
||||
|
||||
private static final ResourceLocation NEW_SPELL_ICON = new ResourceLocation(Wizardry.MODID, "textures/gui/container/new_spell_indicator.png");
|
||||
|
||||
private static final int ICON_WIDTH = 8;
|
||||
private static final int ICON_HEIGHT = 8;
|
||||
|
||||
private static final int ANIMATION_FRAMES = 4;
|
||||
private static final int ANIMATION_FRAME_TIME = 2; // In ticks
|
||||
private static final int ANIMATION_PERIOD = 40; // In frame durations
|
||||
|
||||
private static int tradeIndex; // Mirrors GuiMerchant#selectedMerchantRecipe (don't want to reflect into it every frame)
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public static void onGuiOpenEvent(GuiOpenEvent event){
|
||||
if(event.getGui() instanceof GuiMerchant) tradeIndex = 0;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onActionPerformedPostEvent(ActionPerformedEvent.Post event){
|
||||
|
||||
if(event.getGui() instanceof GuiMerchant){
|
||||
|
||||
MerchantRecipeList recipes = ((GuiMerchant)event.getGui()).getMerchant().getRecipes(Minecraft.getMinecraft().player);
|
||||
|
||||
if(recipes == null) return;
|
||||
|
||||
if(event.getButton().id == 1){ // Next
|
||||
tradeIndex = Math.min(tradeIndex + 1, recipes.size());
|
||||
}else if(event.getButton().id == 2){ // Previous
|
||||
tradeIndex = Math.max(tradeIndex - 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Brute-force fix for crystals not showing up when a wizard is given a spell book in the trade GUI.
|
||||
@SubscribeEvent
|
||||
public static void onGuiDrawForegroundEvent(GuiContainerEvent.DrawForeground event){
|
||||
|
||||
if(event.getGuiContainer() instanceof GuiMerchant){
|
||||
|
||||
GuiMerchant gui = (GuiMerchant)event.getGuiContainer();
|
||||
// Note that gui.getMerchant() returns an NpcMerchant, not an EntityWizard.
|
||||
MerchantRecipeList trades = gui.getMerchant().getRecipes(Minecraft.getMinecraft().player);
|
||||
|
||||
if(trades == null) return;
|
||||
|
||||
// Using == the specific item rather than instanceof because that's how trades do it.
|
||||
if(gui.inventorySlots.getSlot(0).getStack().getItem() == WizardryItems.spell_book
|
||||
|| gui.inventorySlots.getSlot(1).getStack().getItem() == WizardryItems.spell_book){
|
||||
|
||||
for(MerchantRecipe trade : trades){
|
||||
if(trade.getItemToBuy().getItem() == WizardryItems.spell_book && trade.getSecondItemToBuy().isEmpty()){
|
||||
Slot slot = gui.inventorySlots.getSlot(2);
|
||||
// It still doesn't look quite right because the slot highlight is behind the item, but it'll do
|
||||
// until/unless I find a better solution.
|
||||
DrawingUtils.drawItemAndTooltip(gui, trade.getItemToSell(), slot.xPos, slot.yPos, event.getMouseX(), event.getMouseY(),
|
||||
gui.getSlotUnderMouse() == slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// New spell indicator
|
||||
if(gui.inventorySlots instanceof ContainerMerchant){
|
||||
|
||||
// Can't use getCurrentRecipe because that only gets updated when the correct items are given
|
||||
MerchantRecipe recipe = trades.get(tradeIndex);
|
||||
|
||||
if(recipe != null && recipe.getItemToSell().getItem() instanceof ItemSpellBook){
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
Spell spell = Spell.byMetadata(recipe.getItemToSell().getMetadata());
|
||||
|
||||
if(Wizardry.settings.discoveryMode && !player.isCreative() && Wizardry.proxy.shouldDisplayDiscovered(spell, recipe.getItemToSell())
|
||||
&& WizardData.get(player) != null && !WizardData.get(player).hasSpellBeenDiscovered(spell)){
|
||||
|
||||
int x = gui.inventorySlots.getSlot(2).xPos + 14;
|
||||
int y = gui.inventorySlots.getSlot(2).yPos - 17;
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GlStateManager.color(1, 1, 1);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(NEW_SPELL_ICON);
|
||||
|
||||
int frame = Math.max(player.ticksExisted/ANIMATION_FRAME_TIME % ANIMATION_PERIOD - (ANIMATION_PERIOD - ANIMATION_FRAMES), 0);
|
||||
DrawingUtils.drawTexturedRect(x, y, 0, frame * ICON_HEIGHT, ICON_WIDTH, ICON_HEIGHT, ICON_WIDTH, ICON_HEIGHT * ANIMATION_FRAMES);
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
|
||||
// int mouseX = event.getMouseX() - gui.getGuiLeft();
|
||||
// int mouseY = event.getMouseY() - gui.getGuiTop();
|
||||
//
|
||||
// if(mouseX >= x + 1 && mouseX < x + w + 1 && mouseY >= y - 1 && mouseY < y + h + 1){
|
||||
// GuiUtils.drawHoveringText(Collections.singletonList("You haven't discovered this spell yet"), mouseX,
|
||||
// mouseY, gui.width, gui.height, 150, Minecraft.getMinecraft().fontRenderer);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,15 +25,18 @@ public class GuiConfigWizardry extends GuiConfig {
|
||||
|
||||
private static List<IConfigElement> getConfigEntries(){
|
||||
|
||||
List<IConfigElement> configList = new ArrayList<IConfigElement>(1);
|
||||
List<IConfigElement> configList = new ArrayList<>(1);
|
||||
|
||||
configList.add(new DummyCategoryElement("gameplayConfig", "config." + Wizardry.MODID + ".category." + Settings.GAMEPLAY_CATEGORY, GameplayCategory.class));
|
||||
configList.add(new DummyCategoryElement("worldgenConfig", "config." + Wizardry.MODID + ".category." + Settings.WORLDGEN_CATEGORY, WorldgenCategory.class));
|
||||
configList.add(new DummyCategoryElement("commandsConfig", "config." + Wizardry.MODID + ".category." + Settings.COMMANDS_CATEGORY, CommandsCategory.class));
|
||||
configList.add(new DummyCategoryElement("clientConfig", "config." + Wizardry.MODID + ".category." + Settings.CLIENT_CATEGORY, ClientCategory.class));
|
||||
configList.add(new DummyCategoryElement("spellsConfig", "config." + Wizardry.MODID + ".category." + Settings.SPELLS_CATEGORY, SpellsCategory.class));
|
||||
configList.add(new DummyCategoryElement("resistancesConfig", "config." + Wizardry.MODID + ".category." + Settings.RESISTANCES_CATEGORY, ResistancesCategory.class));
|
||||
configList.add(new DummyCategoryElement("compatibilityConfig", "config." + Wizardry.MODID + ".category." + Settings.COMPATIBILITY_CATEGORY, CompatibilityCategory.class));
|
||||
configList.add(new DummyCategoryElement("gameplayConfig", "config." + Wizardry.MODID + ".category." + Settings.GAMEPLAY_CATEGORY, GameplayCategory.class));
|
||||
configList.add(new DummyCategoryElement("difficultyConfig", "config." + Wizardry.MODID + ".category." + Settings.DIFFICULTY_CATEGORY, DifficultyCategory.class));
|
||||
configList.add(new DummyCategoryElement("worldgenConfig", "config." + Wizardry.MODID + ".category." + Settings.WORLDGEN_CATEGORY, WorldgenCategory.class));
|
||||
configList.add(new DummyCategoryElement("tweaksConfig", "config." + Wizardry.MODID + ".category." + Settings.TWEAKS_CATEGORY, TweaksCategory.class));
|
||||
configList.add(new DummyCategoryElement("commandsConfig", "config." + Wizardry.MODID + ".category." + Settings.COMMANDS_CATEGORY, CommandsCategory.class));
|
||||
configList.add(new DummyCategoryElement("clientConfig", "config." + Wizardry.MODID + ".category." + Settings.CLIENT_CATEGORY, ClientCategory.class));
|
||||
configList.add(new DummyCategoryElement("spellsConfig", "config." + Wizardry.MODID + ".category." + Settings.SPELLS_CATEGORY, SpellsCategory.class));
|
||||
configList.add(new DummyCategoryElement("artefactsConfig", "config." + Wizardry.MODID + ".category." + Settings.ARTEFACTS_CATEGORY, ArtefactsCategory.class));
|
||||
configList.add(new DummyCategoryElement("resistancesConfig", "config." + Wizardry.MODID + ".category." + Settings.RESISTANCES_CATEGORY, ResistancesCategory.class));
|
||||
configList.add(new DummyCategoryElement("compatibilityConfig", "config." + Wizardry.MODID + ".category." + Settings.COMPATIBILITY_CATEGORY, CompatibilityCategory.class));
|
||||
|
||||
configList.addAll(new ConfigElement(Wizardry.settings.getConfigCategory(Configuration.CATEGORY_GENERAL)).getChildElements());
|
||||
|
||||
@@ -79,6 +82,16 @@ public class GuiConfigWizardry extends GuiConfig {
|
||||
@Override protected String getCategory() { return Settings.GAMEPLAY_CATEGORY; }
|
||||
}
|
||||
|
||||
/** Difficulty category of the config gui. */
|
||||
public static class DifficultyCategory extends CategoryBase {
|
||||
|
||||
public DifficultyCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
|
||||
super(owningScreen, owningEntryList, prop);
|
||||
}
|
||||
|
||||
@Override protected String getCategory() { return Settings.DIFFICULTY_CATEGORY; }
|
||||
}
|
||||
|
||||
/** Worldgen category of the config gui. */
|
||||
public static class WorldgenCategory extends CategoryBase {
|
||||
|
||||
@@ -89,6 +102,16 @@ public class GuiConfigWizardry extends GuiConfig {
|
||||
@Override protected String getCategory() { return Settings.WORLDGEN_CATEGORY; }
|
||||
}
|
||||
|
||||
/** Tweaks category of the config gui. */
|
||||
public static class TweaksCategory extends CategoryBase {
|
||||
|
||||
public TweaksCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
|
||||
super(owningScreen, owningEntryList, prop);
|
||||
}
|
||||
|
||||
@Override protected String getCategory() { return Settings.TWEAKS_CATEGORY; }
|
||||
}
|
||||
|
||||
/** Commands category of the config gui. */
|
||||
public static class CommandsCategory extends CategoryBase {
|
||||
|
||||
@@ -119,6 +142,16 @@ public class GuiConfigWizardry extends GuiConfig {
|
||||
@Override protected String getCategory() { return Settings.SPELLS_CATEGORY; }
|
||||
}
|
||||
|
||||
/** Artefacts category of the config gui. */
|
||||
public static class ArtefactsCategory extends CategoryBase {
|
||||
|
||||
public ArtefactsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
|
||||
super(owningScreen, owningEntryList, prop);
|
||||
}
|
||||
|
||||
@Override protected String getCategory() { return Settings.ARTEFACTS_CATEGORY; }
|
||||
}
|
||||
|
||||
/** Resistances category of the config gui. */
|
||||
public static class ResistancesCategory extends CategoryBase {
|
||||
|
||||
|
||||
@@ -65,15 +65,15 @@ public class GuiSelectHUDSkin extends GuiSelectString {
|
||||
float scale = Math.min((previewRight - previewLeft - 2*previewBorder)/(float)skin.getWidth(),
|
||||
(previewBottom - previewTop - 2*previewBorder)/(float)skin.getHeight());
|
||||
|
||||
float x = (previewLeft + previewRight)/2 - (skin.getWidth()*scale)/2;
|
||||
float y = (previewBottom + previewTop)/2 + (skin.getHeight()*scale)/2;
|
||||
float x = (previewLeft + previewRight)/2f - (skin.getWidth()*scale)/2;
|
||||
float y = (previewBottom + previewTop)/2f + (skin.getHeight()*scale)/2;
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.scale(scale, scale, scale);
|
||||
|
||||
skin.drawBackground((int)(x/scale), (int)(y/scale), false, false,
|
||||
Spells.magic_missile.getIcon(), 0.6f, false);
|
||||
Spells.magic_missile.getIcon(), 0.6f, false, false);
|
||||
|
||||
skin.drawText((int)(x/scale), (int)(y/scale), false, false,
|
||||
Spells.none.getDisplayNameWithFormatting(),
|
||||
|
||||
@@ -3,7 +3,7 @@ package electroblob.wizardry.client.gui.handbook;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.JavaUtils;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
@@ -50,7 +50,7 @@ class Contents {
|
||||
|
||||
/** Returns an unmodifiable, flattened collection of all the buttons in this contents. */
|
||||
Collection<GuiButton> getButtons(){
|
||||
return WizardryUtilities.flatten(buttons);
|
||||
return JavaUtils.flatten(buttons);
|
||||
}
|
||||
|
||||
void addEntry(Section section){
|
||||
|
||||
@@ -8,7 +8,8 @@ import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.ClientProxy;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.client.gui.GuiButtonInvisible;
|
||||
import electroblob.wizardry.client.gui.handbook.GuiButtonTurnPage.Type;
|
||||
import electroblob.wizardry.client.gui.GuiButtonTurnPage;
|
||||
import electroblob.wizardry.client.gui.GuiButtonTurnPage.Type;
|
||||
import electroblob.wizardry.constants.Constants;
|
||||
import electroblob.wizardry.constants.Element;
|
||||
import electroblob.wizardry.constants.Tier;
|
||||
@@ -54,7 +55,7 @@ public class GuiWizardHandbook extends GuiScreen {
|
||||
|
||||
private static final ResourceLocation DEFAULT = new ResourceLocation(Wizardry.MODID, "texts/handbook_en_us.json");
|
||||
|
||||
static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/handbook.png");
|
||||
static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/handbook/handbook.png");
|
||||
|
||||
/** Global Gson instance for the handbook. */
|
||||
private static final Gson gson = new Gson();
|
||||
@@ -244,6 +245,8 @@ public class GuiWizardHandbook extends GuiScreen {
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks){
|
||||
|
||||
this.drawDefaultBackground();
|
||||
|
||||
int left = this.width / 2 - GUI_WIDTH / 2;
|
||||
int top = this.height / 2 - GUI_HEIGHT / 2;
|
||||
|
||||
@@ -349,19 +352,19 @@ public class GuiWizardHandbook extends GuiScreen {
|
||||
this.buttonList.clear();
|
||||
|
||||
this.buttonList.add(next = new GuiButtonTurnPage(nextButtonId++, left + GUI_WIDTH - BUTTON_INSET_X - GuiButtonTurnPage.WIDTH,
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_PAGE));
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_PAGE, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT));
|
||||
|
||||
this.buttonList.add(previous = new GuiButtonTurnPage(nextButtonId++, left + BUTTON_INSET_X,
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_PAGE));
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_PAGE, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT));
|
||||
|
||||
this.buttonList.add(nextSection = new GuiButtonTurnPage(nextButtonId++, left + GUI_WIDTH - BUTTON_INSET_X - GuiButtonTurnPage.WIDTH - BUTTON_SPACING,
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_SECTION));
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_SECTION, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT));
|
||||
|
||||
this.buttonList.add(previousSection = new GuiButtonTurnPage(nextButtonId++, left + BUTTON_INSET_X + BUTTON_SPACING,
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_SECTION));
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_SECTION, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT));
|
||||
|
||||
this.buttonList.add(menu = new GuiButtonTurnPage(nextButtonId++, left + GUI_WIDTH/2 - 28,
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.CONTENTS));
|
||||
top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.CONTENTS, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT));
|
||||
|
||||
this.buttonList.add(bookmark = new GuiButtonInvisible(nextButtonId++, left + 130, top + 172, 11, 19) {
|
||||
@Override
|
||||
@@ -398,6 +401,11 @@ public class GuiWizardHandbook extends GuiScreen {
|
||||
*/
|
||||
public static void loadHandbookFile(IResourceManager manager){
|
||||
|
||||
if(manager == null){
|
||||
Wizardry.logger.error("Tried to reload the handbook file, but received a null resource manager. Aborting!");
|
||||
return;
|
||||
}
|
||||
|
||||
IResource handbookFile = getHandbookResource(manager);
|
||||
|
||||
if(handbookFile != null){
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.JavaUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
@@ -63,7 +63,7 @@ class Section {
|
||||
}
|
||||
|
||||
Collection<GuiButton> getButtons(){
|
||||
return WizardryUtilities.flatten(buttons);
|
||||
return JavaUtils.flatten(buttons);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import electroblob.wizardry.block.BlockBookshelf;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BakedModelBookshelf implements IBakedModel {
|
||||
|
||||
private final IBakedModel bookshelf;
|
||||
private final IBakedModel[][] books;
|
||||
|
||||
public BakedModelBookshelf(IBakedModel bookshelf, IBakedModel[][] books){
|
||||
this.bookshelf = bookshelf;
|
||||
this.books = books;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand){
|
||||
|
||||
IBakedModel fallback = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelManager().getMissingModel();
|
||||
if(state == null) return fallback.getQuads(null, side, rand);
|
||||
|
||||
// It took me waaay too long to realise I needed a new list here
|
||||
List<BakedQuad> quads = new ArrayList<>(bookshelf.getQuads(state, side, rand)); // Lists ain't immutable, chief
|
||||
|
||||
IExtendedBlockState extendedState = (IExtendedBlockState)state;
|
||||
|
||||
for(int i = 0; i<BlockBookshelf.SLOT_COUNT; i++){
|
||||
Integer value = extendedState.getValue(BlockBookshelf.BOOKS[i]);
|
||||
if(value == null || value < 0) return fallback.getQuads(null, side, rand);
|
||||
if(value < books.length) quads.addAll(books[value][i].getQuads(state, side, rand)); // Empty slots use books.length
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer(){
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delegate everything else to the main bookshelf model
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion(){
|
||||
return bookshelf.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d(){
|
||||
return bookshelf.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture(){
|
||||
return bookshelf.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides(){
|
||||
return bookshelf.getOverrides();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.renderer.block.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.ModelBakeEvent;
|
||||
import net.minecraftforge.client.model.IModel;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A special type of model that generates override models dynamically. This allows the same overrides to be applied to
|
||||
* multiple item models without needing an override version of each one just to point to a texture.
|
||||
* <p></p>
|
||||
* To use this system in a model file:<p></p>
|
||||
* 1. Make a base model file and define the item overrides in it. <b>This model must be placed in the folder
|
||||
* {@code models/item/override_generators}</b> (unfortunately the folder has to be predefined, see below).<br>
|
||||
* 2. Make the model files your overrides point to. These should define everything about the model except textures.<br>
|
||||
* 3. In each model that should generate overrides dynamically, define a single override that points to the location of
|
||||
* the model from step 1 (the predicate doesn't matter).<br>
|
||||
* <p></p>
|
||||
* It is advisable to make the parent of the override model (from step 2) the same as the parent of the model to
|
||||
* be overridden, so that they share any necessary properties and texture variables. For example, both
|
||||
* {@code ebwizardry:item/magic_wand.json} and {@code ebwizardry:item/wand_point.json} have {@code item/handheld} as
|
||||
* their parent. The override model will reference the textures in the original model, so if the override defines a
|
||||
* face with the texture {@code "#face"}, the texture used will be the file associated with {@code "face"} in the
|
||||
* original model. For simple models, this will just be the standard {@code "layer0"}.
|
||||
* @since Wizardry 4.3
|
||||
* @author Electroblob
|
||||
*/
|
||||
// Okay, it's not *that* bad if you only have one override, but imagine having to duplicate every single wand model 5
|
||||
// times if we wanted 5 animations...
|
||||
// The nice thing is resource packs don't lose any flexibility this way, they can still redefine the models themselves
|
||||
// and specify custom models for the overrides if they want, or they can keep using this system - in fact, they GAIN
|
||||
// flexibility because they can also overwrite the base wand.json model and specify global overrides too
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public class BakedModelGenerateOverrides implements IBakedModel {
|
||||
|
||||
// I tried having this as a prefix that gets removed at runtime, which worked fine but it spammed the log with
|
||||
// errors because the prefixed file doesn't actually exist, so even though it's never used the game still complains
|
||||
private static final String OVERRIDE_GENERATORS = "override_generators";
|
||||
|
||||
private final IBakedModel delegate;
|
||||
private final ItemOverrideList overrides;
|
||||
|
||||
public BakedModelGenerateOverrides(IBakedModel delegate, ItemOverrideList overrides){
|
||||
this.delegate = delegate;
|
||||
this.overrides = overrides;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides(){
|
||||
return overrides; // The only thing that's not delegated
|
||||
}
|
||||
|
||||
// Delegate everything else
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand){
|
||||
return delegate.getQuads(state, side, rand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion(){
|
||||
return delegate.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d(){
|
||||
return delegate.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer(){
|
||||
return delegate.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture(){
|
||||
return delegate.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms(){
|
||||
return delegate.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion(IBlockState state){
|
||||
return delegate.isAmbientOcclusion(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType){
|
||||
return delegate.handlePerspective(cameraTransformType);
|
||||
}
|
||||
|
||||
// Baking
|
||||
|
||||
@SubscribeEvent
|
||||
public static void bake(ModelBakeEvent event){
|
||||
|
||||
for(ModelResourceLocation location : event.getModelRegistry().getKeys()){
|
||||
|
||||
IBakedModel original = event.getModelRegistry().getObject(location);
|
||||
|
||||
if(original != null){
|
||||
original.getOverrides().getOverrides().stream().map(ItemOverride::getLocation)
|
||||
.filter(l -> l.getPath().contains(OVERRIDE_GENERATORS)).findFirst()
|
||||
.ifPresent(l -> event.getModelRegistry().putObject(location,
|
||||
substituteWandModel(event.getModelManager(), location, original, l)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have to use ModelBakeEvent for this because we need the original model to be baked with the vanilla system
|
||||
private static IBakedModel substituteWandModel(ModelManager modelManager, ModelResourceLocation location, IBakedModel original, ResourceLocation overrideLocation){
|
||||
|
||||
try {
|
||||
|
||||
IModel unbakedOriginal = ModelLoaderRegistry.getModel(location);
|
||||
IModel referenceModel = ModelLoaderRegistry.getModel(overrideLocation);
|
||||
ModelBlock vanillaOriginal = unbakedOriginal.asVanillaModel().orElse(null);
|
||||
ModelBlock vanillaRefModel = referenceModel.asVanillaModel().orElse(null);
|
||||
|
||||
if(vanillaOriginal != null && vanillaRefModel != null){
|
||||
|
||||
// So... many... data structures...
|
||||
List<ItemOverride> overrides = vanillaRefModel.getOverrides();
|
||||
Map<ResourceLocation, IBakedModel> replacementMap = new HashMap<>();
|
||||
|
||||
for(ItemOverride override : overrides){
|
||||
IModel replacement = ModelLoaderRegistry.getModel(override.getLocation()).retexture(ImmutableMap.copyOf(vanillaOriginal.textures));
|
||||
replacementMap.put(override.getLocation(), replacement.bake(unbakedOriginal.getDefaultState(), DefaultVertexFormats.ITEM, ModelLoader.defaultTextureGetter()));
|
||||
}
|
||||
|
||||
ItemOverrideListMapped overrideList = new ItemOverrideListMapped(overrides, replacementMap);
|
||||
return new BakedModelGenerateOverrides(original, overrideList);
|
||||
}
|
||||
|
||||
}catch(Exception exception){
|
||||
Wizardry.logger.error("Error baking item display override models: ", exception);
|
||||
}
|
||||
|
||||
return modelManager.getMissingModel();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import java.util.List;
|
||||
* <br>
|
||||
* <i>N.B. This doesn't cover item models, and all of the code/model solutions to this that I have tried haven't worked.
|
||||
* However, I noticed that the shade tag seems to work perfectly for items, so instead I've simply duplicated the block
|
||||
* models into the item models folder and add {@code "shade":false} where appropriate. (If it works, it works, right?)</i>
|
||||
* models into the item models folder and add {@code "shade":false} where appropriate. (If it works, it works, right?)</i>
|
||||
*
|
||||
* @author Electroblob
|
||||
* @author raoulvdberge
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverride;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** A version of {@link ItemOverrideList} that uses a predefined map to substitute a specific baked model depending on
|
||||
* the location the currently-applicable override points to. */
|
||||
public class ItemOverrideListMapped extends ItemOverrideList {
|
||||
|
||||
private final Map<ResourceLocation, IBakedModel> replacementMap;
|
||||
|
||||
public ItemOverrideListMapped(List<ItemOverride> overrides, Map<ResourceLocation, IBakedModel> replacementMap){
|
||||
super(overrides);
|
||||
this.replacementMap = ImmutableMap.copyOf(replacementMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity){
|
||||
|
||||
if(!stack.isEmpty() && stack.getItem().hasCustomProperties()){
|
||||
|
||||
// Get the location the original override points to...
|
||||
ResourceLocation location = applyOverride(stack, world, entity); // I wonder why this is deprecated?
|
||||
|
||||
if(location != null){
|
||||
return replacementMap.get(location); // ... then substitute in the corresponding generated model
|
||||
}
|
||||
}
|
||||
|
||||
return originalModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockBookshelf;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.IModel;
|
||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ModelBookshelf implements IModel {
|
||||
|
||||
private static final ResourceLocation DEFAULT_BOOK_TEXTURE = new ResourceLocation(Wizardry.MODID, "blocks/books");
|
||||
|
||||
private static final List<ResourceLocation> bookModelLocations = new ArrayList<>();
|
||||
|
||||
private final ModelResourceLocation bookshelfModelLocation;
|
||||
private final String variant;
|
||||
|
||||
static {
|
||||
for(int i = 0; i < BlockBookshelf.SLOT_COUNT; i++){
|
||||
bookModelLocations.add(new ResourceLocation(Wizardry.MODID, "bookshelf_parts/books" + i));
|
||||
}
|
||||
}
|
||||
|
||||
public ModelBookshelf(String bookshelfModelName){
|
||||
String[] args = bookshelfModelName.split("#", 2);
|
||||
String model = args[0];
|
||||
variant = args.length == 2 ? args[1] : null;
|
||||
bookshelfModelLocation = new ModelResourceLocation(new ResourceLocation(Wizardry.MODID, "bookshelf_parts/" + model), variant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter){
|
||||
|
||||
try {
|
||||
|
||||
IModel bookshelfModel = ModelLoaderRegistry.getModel(bookshelfModelLocation);
|
||||
// I don't know why default state works here (surely it ought to be the state param?), but it works so who cares
|
||||
IBakedModel bookshelf = bookshelfModel.bake(bookshelfModel.getDefaultState(), format, bakedTextureGetter);
|
||||
|
||||
ImmutableList<ResourceLocation> textures = BlockBookshelf.getBookTextures();
|
||||
|
||||
IBakedModel[][] books = new IBakedModel[textures.size()][BlockBookshelf.SLOT_COUNT];
|
||||
|
||||
for(int i = 0; i < textures.size(); i++){
|
||||
|
||||
ImmutableMap<String, String> retexturer = ImmutableMap.of("books", textures.get(i).toString());
|
||||
|
||||
for(int j = 0; j < BlockBookshelf.SLOT_COUNT; j++){
|
||||
IModel bookModel = ModelLoaderRegistry.getModel(new ModelResourceLocation(bookModelLocations.get(j), variant)).retexture(retexturer);
|
||||
books[i][j] = bookModel.bake(bookModel.getDefaultState(), format, bakedTextureGetter); // Same here!
|
||||
}
|
||||
}
|
||||
|
||||
// To clarify: the whole point of doing this was to avoid having to bake 4 * 2^12 models per bookshelf type
|
||||
// Therefore we have to have a baked bookshelf model that's kind of dynamic
|
||||
return new BakedModelBookshelf(bookshelf, books);
|
||||
|
||||
}catch(Exception exception){
|
||||
Wizardry.logger.error("Error baking bookshelf models: ", exception);
|
||||
return ModelLoaderRegistry.getMissingModel().bake(state, format, bakedTextureGetter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies(){
|
||||
return bookModelLocations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getTextures(){
|
||||
|
||||
// I simply have no idea how I'm *supposed* to do it, so I'm using the best solution I can come up with
|
||||
// This is at least better than manually registering it with TextureStitchEvent
|
||||
// However I'm also pretty sure that if a texture pack decides to change the texture that the book models point
|
||||
// to, it won't work... but since nobody ever will, I don't really care!
|
||||
|
||||
// Why am I confused?
|
||||
// 1. How come it magically finds the bookshelf texture, but not the book texture?
|
||||
// 2. Why don't the textures get retrieved automatically based on getDependencies? Surely that's the point?
|
||||
// 3. Is it correct to use getModel() to get the dependency models upon construction of this class so I can
|
||||
// access their textures properly? Or is that too early?
|
||||
// 4. If so, what's the point of getDependencies, and why should I override it?
|
||||
return BlockBookshelf.getBookTextures();// ImmutableList.of(DEFAULT_BOOK_TEXTURE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelBox;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
// Made with Blockbench 3.5.2
|
||||
public class ModelBoulder extends ModelBase {
|
||||
|
||||
private final ModelRenderer mainGroup;
|
||||
private final ModelRenderer box1;
|
||||
private final ModelRenderer box2;
|
||||
private final ModelRenderer box3;
|
||||
private final ModelRenderer box4;
|
||||
private final ModelRenderer box5;
|
||||
private final ModelRenderer box6;
|
||||
|
||||
public ModelBoulder(){
|
||||
|
||||
textureWidth = 64;
|
||||
textureHeight = 32;
|
||||
|
||||
mainGroup = new ModelRenderer(this);
|
||||
mainGroup.setRotationPoint(0.0F, 24.0F, 0.0F);
|
||||
|
||||
box1 = new ModelRenderer(this);
|
||||
box1.setRotationPoint(0.0F, -19.0F, 0.0F);
|
||||
mainGroup.addChild(box1);
|
||||
box1.cubeList.add(new ModelBox(box1, 0, 0, -11.0F, -11.0F, 11.0F, 22, 22, 8, 0.0F, false));
|
||||
|
||||
box2 = new ModelRenderer(this);
|
||||
box2.setRotationPoint(0.0F, -19.0F, 0.0F);
|
||||
mainGroup.addChild(box2);
|
||||
setRotationAngle(box2, -1.5708F, 0.0F, 0.0F);
|
||||
box2.cubeList.add(new ModelBox(box2, 0, 0, -11.0F, -11.0F, 11.0F, 22, 22, 8, 0.0F, false));
|
||||
|
||||
box3 = new ModelRenderer(this);
|
||||
box3.setRotationPoint(0.0F, -19.0F, 0.0F);
|
||||
mainGroup.addChild(box3);
|
||||
setRotationAngle(box3, 0.0F, -1.5708F, 0.0F);
|
||||
box3.cubeList.add(new ModelBox(box3, 0, 0, -11.0F, -11.0F, 11.0F, 22, 22, 8, 0.0F, false));
|
||||
|
||||
box4 = new ModelRenderer(this);
|
||||
box4.setRotationPoint(0.0F, -19.0F, 0.0F);
|
||||
mainGroup.addChild(box4);
|
||||
setRotationAngle(box4, 0.0F, 1.5708F, 0.0F);
|
||||
box4.cubeList.add(new ModelBox(box4, 0, 0, -11.0F, -11.0F, 11.0F, 22, 22, 8, 0.0F, false));
|
||||
|
||||
box5 = new ModelRenderer(this);
|
||||
box5.setRotationPoint(0.0F, -19.0F, 0.0F);
|
||||
mainGroup.addChild(box5);
|
||||
setRotationAngle(box5, 1.5708F, 0.0F, 0.0F);
|
||||
box5.cubeList.add(new ModelBox(box5, 0, 0, -11.0F, -11.0F, 11.0F, 22, 22, 8, 0.0F, false));
|
||||
|
||||
box6 = new ModelRenderer(this);
|
||||
box6.setRotationPoint(0.0F, -19.0F, 0.0F);
|
||||
mainGroup.addChild(box6);
|
||||
setRotationAngle(box6, 3.1416F, 0.0F, 0.0F);
|
||||
box6.cubeList.add(new ModelBox(box6, 0, 0, -11.0F, -11.0F, 11.0F, 22, 22, 8, 0.0F, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){
|
||||
mainGroup.render(f5);
|
||||
}
|
||||
|
||||
public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z){
|
||||
modelRenderer.rotateAngleX = x;
|
||||
modelRenderer.rotateAngleY = y;
|
||||
modelRenderer.rotateAngleZ = z;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelBox;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
// Made with Blockbench 3.5.4
|
||||
public class ModelIceBarrier extends ModelBase {
|
||||
|
||||
private final ModelRenderer mainGroup;
|
||||
|
||||
public ModelIceBarrier(){
|
||||
|
||||
textureWidth = 64;
|
||||
textureHeight = 64;
|
||||
|
||||
mainGroup = new ModelRenderer(this);
|
||||
mainGroup.setRotationPoint(0.0F, 24.0F, 0.0F);
|
||||
setRotationAngle(mainGroup, 0.0F, 0.0F, 0.7854F);
|
||||
mainGroup.cubeList.add(new ModelBox(mainGroup, 0, 0, -14.5F, -14.5F, -1.5F, 29, 29, 3, 0.0F, false));
|
||||
mainGroup.cubeList.add(new ModelBox(mainGroup, 0, 32, -9.0F, -9.0F, -4.0F, 18, 18, 8, 0.0F, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
|
||||
mainGroup.render(f5);
|
||||
}
|
||||
|
||||
public void setRotationAngle(ModelRenderer modelRenderer, float x, float y, float z) {
|
||||
modelRenderer.rotateAngleX = x;
|
||||
modelRenderer.rotateAngleY = y;
|
||||
modelRenderer.rotateAngleZ = z;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.ICustomModelLoader;
|
||||
import net.minecraftforge.client.model.IModel;
|
||||
|
||||
public class ModelLoaderBookshelf implements ICustomModelLoader {
|
||||
|
||||
private static final String SMART_MODEL_PREFIX = "models/block/smart_model/";
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager){
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(ResourceLocation modelLocation){
|
||||
return modelLocation.getNamespace().equals(Wizardry.MODID) && modelLocation.getPath().startsWith(SMART_MODEL_PREFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModel loadModel(ResourceLocation modelLocation){
|
||||
return new ModelBookshelf(modelLocation.getPath().substring(SMART_MODEL_PREFIX.length()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
/** Based on ModelEnderCrystal */
|
||||
public class ModelRemnant extends ModelBase {
|
||||
|
||||
private final ModelRenderer cube = new ModelRenderer(this, "cube");
|
||||
|
||||
public ModelRemnant(){
|
||||
this.cube.setTextureOffset(0, 0).addBox(-4.0F, -4.0F, -4.0F, 8, 8, 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, float rotationSpeed, float expandFraction, float age, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
// GlStateManager.scale(2.0F, 2.0F, 2.0F);
|
||||
// GlStateManager.translate(0.0F, -0.5F, 0.0F);
|
||||
|
||||
GlStateManager.disableCull();
|
||||
|
||||
GlStateManager.translate(0.0F, entity.height/2, 0.0F);
|
||||
|
||||
float s = expandFraction + MathHelper.sin(age * 0.1f) * 0.06f;
|
||||
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
GlStateManager.rotate(age * rotationSpeed/2, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(60.0F, 0.7071F, 0.0F, 0.7071F);
|
||||
GlStateManager.rotate(age * rotationSpeed, 0.0F, 1.0F, 0.0F);
|
||||
this.cube.render(scale);
|
||||
|
||||
GlStateManager.scale(0.875F, 0.875F, 0.875F);
|
||||
GlStateManager.rotate(60.0F, 0.7071F, 0.0F, 0.7071F);
|
||||
GlStateManager.rotate(age * rotationSpeed, 0.0F, 1.0F, 0.0F);
|
||||
this.cube.render(scale);
|
||||
|
||||
GlStateManager.enableCull();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,12 @@ import electroblob.wizardry.block.BlockCrystal;
|
||||
import electroblob.wizardry.block.BlockPedestal;
|
||||
import electroblob.wizardry.block.BlockRunestone;
|
||||
import electroblob.wizardry.item.IMultiTexturedItem;
|
||||
import electroblob.wizardry.item.ItemBlockMultiTexturedElemental;
|
||||
import electroblob.wizardry.item.ItemBlockMultiTextured;
|
||||
import electroblob.wizardry.item.ItemCrystal;
|
||||
import electroblob.wizardry.item.ItemSpectralDust;
|
||||
import electroblob.wizardry.registry.WizardryBlocks;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import net.minecraft.block.BlockPlanks;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ModelBakery;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
@@ -20,11 +22,15 @@ import net.minecraft.util.NonNullList;
|
||||
import net.minecraftforge.client.event.ModelBakeEvent;
|
||||
import net.minecraftforge.client.event.ModelRegistryEvent;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class responsible for registering all of wizardry's item and block models.
|
||||
*
|
||||
@@ -37,32 +43,39 @@ public final class WizardryModels {
|
||||
|
||||
private WizardryModels(){} // No instances!
|
||||
|
||||
/** Keeps track of all items whose models have been registered manually to exclude them from automatic registry of
|
||||
* standard item models. Internal only, this gets cleared once model registry is complete. */
|
||||
private static final List<Item> registeredItems = new ArrayList<>();
|
||||
|
||||
@SubscribeEvent
|
||||
public static void register(ModelRegistryEvent event){
|
||||
|
||||
// ItemBlocks
|
||||
|
||||
registerItemModel(Item.getItemFromBlock(WizardryBlocks.arcane_workbench));
|
||||
registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_ore));
|
||||
registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_flower));
|
||||
registerItemModel(Item.getItemFromBlock(WizardryBlocks.transportation_stone));
|
||||
|
||||
ModelLoader.setCustomStateMapper(WizardryBlocks.crystal_block, new StateMap.Builder()
|
||||
.withName(BlockCrystal.ELEMENT).withSuffix("_crystal_block").build());
|
||||
// Yay unchecked casting! But we know it's always ok here, and it makes everything much neater.
|
||||
ItemBlockMultiTexturedElemental crystalBlockItem = (ItemBlockMultiTexturedElemental)Item.getItemFromBlock(WizardryBlocks.crystal_block);
|
||||
ItemBlockMultiTextured crystalBlockItem = (ItemBlockMultiTextured)Item.getItemFromBlock(WizardryBlocks.crystal_block);
|
||||
registerMultiTexturedModel(crystalBlockItem);
|
||||
|
||||
ModelLoader.setCustomStateMapper(WizardryBlocks.runestone, new StateMap.Builder()
|
||||
.withName(BlockRunestone.ELEMENT).withSuffix("_runestone").build());
|
||||
ItemBlockMultiTexturedElemental runestoneItem = (ItemBlockMultiTexturedElemental)Item.getItemFromBlock(WizardryBlocks.runestone);
|
||||
ItemBlockMultiTextured runestoneItem = (ItemBlockMultiTextured)Item.getItemFromBlock(WizardryBlocks.runestone);
|
||||
registerMultiTexturedModel(runestoneItem);
|
||||
|
||||
ModelLoader.setCustomStateMapper(WizardryBlocks.runestone_pedestal, new StateMap.Builder()
|
||||
.withName(BlockPedestal.ELEMENT).ignore(BlockPedestal.NATURAL).withSuffix("_runestone_pedestal").build()); // Don't care about NATURAL property
|
||||
ItemBlockMultiTexturedElemental pedestalItem = (ItemBlockMultiTexturedElemental)Item.getItemFromBlock(WizardryBlocks.runestone_pedestal);
|
||||
ItemBlockMultiTextured pedestalItem = (ItemBlockMultiTextured)Item.getItemFromBlock(WizardryBlocks.runestone_pedestal);
|
||||
registerMultiTexturedModel(pedestalItem);
|
||||
|
||||
ModelLoader.setCustomStateMapper(WizardryBlocks.gilded_wood, new StateMap.Builder()
|
||||
.withName(BlockPlanks.VARIANT).withSuffix("_gilded_wood").build());
|
||||
ItemBlockMultiTextured gildedWoodItem = (ItemBlockMultiTextured)Item.getItemFromBlock(WizardryBlocks.gilded_wood);
|
||||
registerMultiTexturedModel(gildedWoodItem);
|
||||
|
||||
// Explanation for all this here -> https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe05_block_dynamic_block_model2
|
||||
ModelLoaderRegistry.registerLoader(new ModelLoaderBookshelf());
|
||||
|
||||
// Items
|
||||
|
||||
registerMultiTexturedModel((ItemCrystal)WizardryItems.magic_crystal);
|
||||
@@ -72,11 +85,9 @@ public final class WizardryModels {
|
||||
registerWandModel(WizardryItems.advanced_wand);
|
||||
registerWandModel(WizardryItems.master_wand);
|
||||
|
||||
registerItemModel(WizardryItems.spell_book);
|
||||
registerItemModel(WizardryItems.spell_book); // Also need this or auto-registry will ignore it
|
||||
// Wildcard registered for wizard trades.
|
||||
registerItemModel(WizardryItems.spell_book, OreDictionary.WILDCARD_VALUE, "normal");
|
||||
registerItemModel(WizardryItems.arcane_tome);
|
||||
registerItemModel(WizardryItems.wizard_handbook);
|
||||
|
||||
registerWandModel(WizardryItems.novice_fire_wand);
|
||||
registerWandModel(WizardryItems.novice_ice_wand);
|
||||
@@ -110,160 +121,16 @@ public final class WizardryModels {
|
||||
registerWandModel(WizardryItems.master_sorcery_wand);
|
||||
registerWandModel(WizardryItems.master_healing_wand);
|
||||
|
||||
registerItemModel(WizardryItems.spectral_sword);
|
||||
registerItemModel(WizardryItems.spectral_pickaxe);
|
||||
registerItemModel(WizardryItems.spectral_bow);
|
||||
registerMultiTexturedModel((ItemSpectralDust)WizardryItems.spectral_dust);
|
||||
|
||||
registerItemModel(WizardryItems.small_mana_flask);
|
||||
registerItemModel(WizardryItems.medium_mana_flask);
|
||||
registerItemModel(WizardryItems.large_mana_flask);
|
||||
|
||||
registerItemModel(WizardryItems.crystal_shard);
|
||||
registerItemModel(WizardryItems.grand_crystal);
|
||||
|
||||
registerItemModel(WizardryItems.astral_diamond);
|
||||
|
||||
registerItemModel(WizardryItems.purifying_elixir);
|
||||
|
||||
registerItemModel(WizardryItems.storage_upgrade);
|
||||
registerItemModel(WizardryItems.siphon_upgrade);
|
||||
registerItemModel(WizardryItems.condenser_upgrade);
|
||||
registerItemModel(WizardryItems.range_upgrade);
|
||||
registerItemModel(WizardryItems.duration_upgrade);
|
||||
registerItemModel(WizardryItems.cooldown_upgrade);
|
||||
registerItemModel(WizardryItems.blast_upgrade);
|
||||
registerItemModel(WizardryItems.attunement_upgrade);
|
||||
registerItemModel(WizardryItems.melee_upgrade);
|
||||
|
||||
registerItemModel(WizardryItems.flaming_axe);
|
||||
registerItemModel(WizardryItems.frost_axe);
|
||||
|
||||
registerItemModel(WizardryItems.firebomb);
|
||||
registerItemModel(WizardryItems.poison_bomb);
|
||||
registerItemModel(WizardryItems.smoke_bomb);
|
||||
registerItemModel(WizardryItems.spark_bomb);
|
||||
|
||||
registerItemModel(WizardryItems.blank_scroll);
|
||||
registerItemModel(WizardryItems.scroll);
|
||||
registerItemModel(WizardryItems.identification_scroll);
|
||||
|
||||
registerItemModel(WizardryItems.armour_upgrade);
|
||||
|
||||
registerItemModel(WizardryItems.magic_silk);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat);
|
||||
registerItemModel(WizardryItems.wizard_robe);
|
||||
registerItemModel(WizardryItems.wizard_leggings);
|
||||
registerItemModel(WizardryItems.wizard_boots);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat_fire);
|
||||
registerItemModel(WizardryItems.wizard_robe_fire);
|
||||
registerItemModel(WizardryItems.wizard_leggings_fire);
|
||||
registerItemModel(WizardryItems.wizard_boots_fire);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat_ice);
|
||||
registerItemModel(WizardryItems.wizard_robe_ice);
|
||||
registerItemModel(WizardryItems.wizard_leggings_ice);
|
||||
registerItemModel(WizardryItems.wizard_boots_ice);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat_lightning);
|
||||
registerItemModel(WizardryItems.wizard_robe_lightning);
|
||||
registerItemModel(WizardryItems.wizard_leggings_lightning);
|
||||
registerItemModel(WizardryItems.wizard_boots_lightning);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat_necromancy);
|
||||
registerItemModel(WizardryItems.wizard_robe_necromancy);
|
||||
registerItemModel(WizardryItems.wizard_leggings_necromancy);
|
||||
registerItemModel(WizardryItems.wizard_boots_necromancy);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat_earth);
|
||||
registerItemModel(WizardryItems.wizard_robe_earth);
|
||||
registerItemModel(WizardryItems.wizard_leggings_earth);
|
||||
registerItemModel(WizardryItems.wizard_boots_earth);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat_sorcery);
|
||||
registerItemModel(WizardryItems.wizard_robe_sorcery);
|
||||
registerItemModel(WizardryItems.wizard_leggings_sorcery);
|
||||
registerItemModel(WizardryItems.wizard_boots_sorcery);
|
||||
|
||||
registerItemModel(WizardryItems.wizard_hat_healing);
|
||||
registerItemModel(WizardryItems.wizard_robe_healing);
|
||||
registerItemModel(WizardryItems.wizard_leggings_healing);
|
||||
registerItemModel(WizardryItems.wizard_boots_healing);
|
||||
|
||||
registerItemModel(WizardryItems.spectral_helmet);
|
||||
registerItemModel(WizardryItems.spectral_chestplate);
|
||||
registerItemModel(WizardryItems.spectral_leggings);
|
||||
registerItemModel(WizardryItems.spectral_boots);
|
||||
|
||||
registerItemModel(WizardryItems.lightning_hammer);
|
||||
|
||||
registerItemModel(WizardryItems.ring_condensing);
|
||||
registerItemModel(WizardryItems.ring_siphoning);
|
||||
registerItemModel(WizardryItems.ring_battlemage);
|
||||
registerItemModel(WizardryItems.ring_combustion);
|
||||
registerItemModel(WizardryItems.ring_fire_melee);
|
||||
registerItemModel(WizardryItems.ring_fire_biome);
|
||||
registerItemModel(WizardryItems.ring_disintegration);
|
||||
registerItemModel(WizardryItems.ring_ice_melee);
|
||||
registerItemModel(WizardryItems.ring_ice_biome);
|
||||
registerItemModel(WizardryItems.ring_arcane_frost);
|
||||
registerItemModel(WizardryItems.ring_shattering);
|
||||
registerItemModel(WizardryItems.ring_lightning_melee);
|
||||
registerItemModel(WizardryItems.ring_storm);
|
||||
registerItemModel(WizardryItems.ring_seeking);
|
||||
registerItemModel(WizardryItems.ring_hammer);
|
||||
registerItemModel(WizardryItems.ring_soulbinding);
|
||||
registerItemModel(WizardryItems.ring_leeching);
|
||||
registerItemModel(WizardryItems.ring_necromancy_melee);
|
||||
registerItemModel(WizardryItems.ring_mind_control);
|
||||
registerItemModel(WizardryItems.ring_poison);
|
||||
registerItemModel(WizardryItems.ring_earth_melee);
|
||||
registerItemModel(WizardryItems.ring_earth_biome);
|
||||
registerItemModel(WizardryItems.ring_full_moon);
|
||||
registerItemModel(WizardryItems.ring_extraction);
|
||||
registerItemModel(WizardryItems.ring_mana_return);
|
||||
registerItemModel(WizardryItems.ring_blockwrangler);
|
||||
registerItemModel(WizardryItems.ring_conjurer);
|
||||
registerItemModel(WizardryItems.ring_defender);
|
||||
registerItemModel(WizardryItems.ring_paladin);
|
||||
registerItemModel(WizardryItems.ring_interdiction);
|
||||
|
||||
registerItemModel(WizardryItems.amulet_arcane_defence);
|
||||
registerItemModel(WizardryItems.amulet_warding);
|
||||
registerItemModel(WizardryItems.amulet_wisdom);
|
||||
registerItemModel(WizardryItems.amulet_fire_protection);
|
||||
registerItemModel(WizardryItems.amulet_fire_cloaking);
|
||||
registerItemModel(WizardryItems.amulet_ice_immunity);
|
||||
registerItemModel(WizardryItems.amulet_ice_protection);
|
||||
registerItemModel(WizardryItems.amulet_potential);
|
||||
registerItemModel(WizardryItems.amulet_channeling);
|
||||
registerItemModel(WizardryItems.amulet_lich);
|
||||
registerItemModel(WizardryItems.amulet_wither_immunity);
|
||||
registerItemModel(WizardryItems.amulet_glide);
|
||||
registerItemModel(WizardryItems.amulet_banishing);
|
||||
registerItemModel(WizardryItems.amulet_anchoring);
|
||||
registerItemModel(WizardryItems.amulet_recovery);
|
||||
registerItemModel(WizardryItems.amulet_transience);
|
||||
registerItemModel(WizardryItems.amulet_resurrection);
|
||||
registerItemModel(WizardryItems.amulet_auto_shield);
|
||||
|
||||
registerItemModel(WizardryItems.charm_haggler);
|
||||
registerItemModel(WizardryItems.charm_experience_tome);
|
||||
registerItemModel(WizardryItems.charm_auto_smelt);
|
||||
registerItemModel(WizardryItems.charm_lava_walking);
|
||||
registerItemModel(WizardryItems.charm_storm);
|
||||
registerItemModel(WizardryItems.charm_minion_health);
|
||||
registerItemModel(WizardryItems.charm_minion_variants);
|
||||
registerItemModel(WizardryItems.charm_flight);
|
||||
registerItemModel(WizardryItems.charm_growth);
|
||||
registerItemModel(WizardryItems.charm_abseiling);
|
||||
registerItemModel(WizardryItems.charm_silk_touch);
|
||||
registerItemModel(WizardryItems.charm_stop_time);
|
||||
registerItemModel(WizardryItems.charm_light);
|
||||
registerItemModel(WizardryItems.charm_transportation);
|
||||
registerItemModel(WizardryItems.charm_feeding);
|
||||
// Automatic item model registry
|
||||
for(Item item : Item.REGISTRY){
|
||||
if(!registeredItems.contains(item) && item.getRegistryName().getNamespace().equals(Wizardry.MODID)){
|
||||
registerItemModel(item); // Standard item model
|
||||
}
|
||||
}
|
||||
|
||||
registeredItems.clear(); // Might as well clean this up
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -280,11 +147,12 @@ public final class WizardryModels {
|
||||
|
||||
if(location.getNamespace().equals(Wizardry.MODID)){
|
||||
|
||||
if(location.getPath().contains("runestone") || location.getPath().contains("runestone_pedestal")){
|
||||
IBakedModel original = event.getModelRegistry().getObject(location);
|
||||
IBakedModel original = event.getModelRegistry().getObject(location);
|
||||
|
||||
if(location.getPath().contains("runestone") || location.getPath().contains("runestone_pedestal")
|
||||
|| location.getPath().endsWith("imbuement_altar")){ // Ends with to exclude inactive version
|
||||
event.getModelRegistry().putObject(location, new BakedModelGlowingOverlay(original, "overlay"));
|
||||
}else if(location.getPath().contains("spectral_block")){
|
||||
IBakedModel original = event.getModelRegistry().getObject(location);
|
||||
event.getModelRegistry().putObject(location, new BakedModelGlowingOverlay(original, "spectral_block"));
|
||||
}
|
||||
}
|
||||
@@ -302,6 +170,7 @@ public final class WizardryModels {
|
||||
ModelBakery.registerItemVariants(item, new ModelResourceLocation(item.getRegistryName(), "inventory"));
|
||||
// Assigns the model for all metadata values
|
||||
ModelLoader.setCustomMeshDefinition(item, s -> new ModelResourceLocation(item.getRegistryName(), "inventory"));
|
||||
registeredItems.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,6 +184,7 @@ public final class WizardryModels {
|
||||
ModelBakery.registerItemVariants(item, new ModelResourceLocation("ebwizardry:festive_wand", "inventory"));
|
||||
// Assigns the model for all metadata values
|
||||
ModelLoader.setCustomMeshDefinition(item, s -> new ModelResourceLocation("ebwizardry:festive_wand", "inventory"));
|
||||
registeredItems.add(item);
|
||||
}else{
|
||||
registerItemModel(item);
|
||||
}
|
||||
@@ -338,6 +208,8 @@ public final class WizardryModels {
|
||||
new ModelResourceLocation(item.getModelName(stack), "inventory"));
|
||||
}
|
||||
}
|
||||
|
||||
registeredItems.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,6 +220,7 @@ public final class WizardryModels {
|
||||
private static void registerItemModel(Item item, int metadata, String variant){
|
||||
ModelLoader.setCustomModelResourceLocation(item, metadata,
|
||||
new ModelResourceLocation(item.getRegistryName(), variant));
|
||||
registeredItems.add(item); // Still ought to do this in case I ever use this method alone for an item
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package electroblob.wizardry.client.particle;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
//@SideOnly(Side.CLIENT)
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public class ParticleBlockHighlight extends ParticleWizardry {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "particle/block_highlight");
|
||||
|
||||
public ParticleBlockHighlight(World world, double x, double y, double z){
|
||||
|
||||
super(world, x, y, z, TEXTURE);
|
||||
|
||||
this.particleGravity = 0;
|
||||
this.setMaxAge(160);
|
||||
// 5 makes it the exact size of a block face, plus a little bit to account for the anti-z-fighting offset
|
||||
this.particleScale = 5 * (1 + 2 * (float)GeometryUtils.ANTI_Z_FIGHTING_OFFSET);
|
||||
this.shaded = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDisableDepth(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(){
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
// Fading
|
||||
if(this.particleAge > this.particleMaxAge/2){
|
||||
this.setAlphaF(1 - ((float)this.particleAge - this.particleMaxAge/2f) / (this.particleMaxAge/2f));
|
||||
}
|
||||
|
||||
EnumFacing facing = EnumFacing.fromAngle(yaw);
|
||||
if(pitch == 90) facing = EnumFacing.UP;
|
||||
if(pitch == -90) facing = EnumFacing.DOWN;
|
||||
|
||||
// Disappears if there is no block behind it (this is the same check used to spawn it)
|
||||
if(!world.getBlockState(new BlockPos(posX, posY, posZ).offset(facing.getOpposite())).getMaterial().isSolid()){
|
||||
this.setExpired();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTextureStitchEvent(TextureStitchEvent.Pre event){
|
||||
event.getMap().registerSprite(TEXTURE);
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class ParticleBuff extends ParticleWizardry {
|
||||
float rotationYZ, float rotationXY, float rotationXZ){
|
||||
|
||||
// Copied from ParticleWizardry, needs to be here since we're not calling super
|
||||
updateEntityLinking(partialTicks);
|
||||
updateEntityLinking(viewer, partialTicks);
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.pushAttrib();
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package electroblob.wizardry.client.particle;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public class ParticleCloud extends ParticleWizardry {
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = generateTextures("cloud", 4);
|
||||
|
||||
public ParticleCloud(World world, double x, double y, double z){
|
||||
|
||||
super(world, x, y, z, TEXTURES[world.rand.nextInt(TEXTURES.length)]);
|
||||
|
||||
this.setRBGColorF(1, 1, 1);
|
||||
this.particleMaxAge = 48 + this.rand.nextInt(12);
|
||||
this.particleScale *= 6;
|
||||
this.setGravity(false);
|
||||
this.setAlphaF(0);
|
||||
this.canCollide = false;
|
||||
this.shaded = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDisableDepth(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(){
|
||||
|
||||
super.onUpdate();
|
||||
|
||||
// Fading
|
||||
float fadeTime = this.particleMaxAge * 0.3f;
|
||||
this.setAlphaF(MathHelper.clamp(Math.min(this.particleAge / fadeTime, (this.particleMaxAge - this.particleAge) / fadeTime), 0, 1));
|
||||
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTextureStitchEvent(TextureStitchEvent.Pre event){
|
||||
for(ResourceLocation texture : TEXTURES){
|
||||
event.getMap().registerSprite(texture);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,15 +17,4 @@ public class ParticleDust extends ParticleWizardry {
|
||||
this.setRBGColorF(1, 1, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(){
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
this.prevPosZ = this.posZ;
|
||||
this.move(this.motionX, this.motionY, this.motionZ);
|
||||
|
||||
if(this.particleMaxAge-- <= 0){
|
||||
this.setExpired();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,15 +35,10 @@ public class ParticleFlash extends ParticleWizardry {
|
||||
int i = this.getBrightnessForRender(partialTicks);
|
||||
int j = i >> 16 & 65535;
|
||||
int k = i & 65535;
|
||||
buffer.pos((double)(f5 - rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 - rotationYZ * f4 - rotationXZ * f4)).tex(0.5D, 0.375D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
buffer.pos((double)(f5 - rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 - rotationYZ * f4 + rotationXZ * f4)).tex(0.5D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
buffer.pos((double)(f5 + rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 + rotationYZ * f4 + rotationXZ * f4)).tex(0.25D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
buffer.pos((double)(f5 + rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 + rotationYZ * f4 - rotationXZ * f4)).tex(0.25D, 0.375D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightnessForRender(float partialTicks){
|
||||
return 15728880;
|
||||
buffer.pos(f5 - rotationX * f4 - rotationXY * f4, f6 - rotationZ * f4, f7 - rotationYZ * f4 - rotationXZ * f4).tex(0.5D, 0.375D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
buffer.pos(f5 - rotationX * f4 + rotationXY * f4, f6 + rotationZ * f4, f7 - rotationYZ * f4 + rotationXZ * f4).tex(0.5D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
buffer.pos(f5 + rotationX * f4 + rotationXY * f4, f6 + rotationZ * f4, f7 + rotationYZ * f4 + rotationXZ * f4).tex(0.25D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
buffer.pos(f5 + rotationX * f4 - rotationXY * f4, f6 - rotationZ * f4, f7 + rotationYZ * f4 - rotationXZ * f4).tex(0.25D, 0.375D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package electroblob.wizardry.client.particle;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class ParticleGuardianBeam extends ParticleTargeted {
|
||||
|
||||
/** Half the width of the beam. */
|
||||
private static final float THICKNESS = 0.15f;
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation("minecraft:textures/entity/guardian_beam.png");
|
||||
|
||||
public ParticleGuardianBeam(World world, double x, double y, double z){
|
||||
super(world, x, y, z); // Does't use TextureAtlasSprite
|
||||
this.setRBGColorF(1, 1, 1);
|
||||
this.setMaxAge(3);
|
||||
this.particleScale = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFXLayer(){
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void draw(Tessellator tessellator, double length, float partialTicks){
|
||||
|
||||
float scale = this.particleScale;
|
||||
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
// Enables texture tiling (Also used for guardian beam, beacon beam and ender crystal beam, amongst others)
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
|
||||
GlStateManager.rotate(Minecraft.getMinecraft().player.ticksExisted + partialTicks, 0, 0, 1);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURE);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
|
||||
|
||||
float t = THICKNESS * scale;
|
||||
float v1 = 2 * (particleAge + partialTicks) / particleMaxAge;
|
||||
float v2 = v1 + (float)length * 2; // Multiply by 2 to make it squished like it is in vanilla
|
||||
|
||||
buffer.pos(-t, 0, 0) .tex(0, v1) .color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
buffer.pos( t, 0, 0) .tex(0.5, v1) .color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
buffer.pos( t, 0, length).tex(0.5, v2).color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
buffer.pos(-t, 0, length).tex(0, v2).color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
|
||||
buffer.pos(0, -t, 0) .tex(0, v1) .color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
buffer.pos(0, t, 0) .tex(0.5, v1) .color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
buffer.pos(0, t, length).tex(0.5, v2).color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
buffer.pos(0, -t, length).tex(0, v2).color(particleRed, particleGreen, particleBlue, 1).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
// GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
// GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
// Makes the rain go weird
|
||||
//GlStateManager.enableLighting();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,7 +41,7 @@ public class ParticleSphere extends ParticleWizardry {
|
||||
float rotationXY, float rotationXZ){
|
||||
|
||||
// Copied from ParticleWizardry, needs to be here since we're not calling super
|
||||
updateEntityLinking(partialTicks);
|
||||
updateEntityLinking(viewer, partialTicks);
|
||||
|
||||
float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks);
|
||||
float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks);
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
package electroblob.wizardry.client.particle;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
//@SideOnly(Side.CLIENT)
|
||||
public class ParticleSummon extends ParticleWizardry {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/particle/summon.png");
|
||||
private final boolean mirror;
|
||||
|
||||
public ParticleSummon(World world, double x, double y, double z){
|
||||
super(world, x, y, z);
|
||||
this.mirror = random.nextBoolean();
|
||||
this.setMaxAge(10);
|
||||
this.setGravity(false);
|
||||
this.canCollide = false;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onUpdate(){
|
||||
// super.onUpdate();
|
||||
// if(this.particleAge > this.particleMaxAge/2) this.particleAlpha = 2f - 2f*(float)this.particleAge/(float)this.particleMaxAge;
|
||||
// }
|
||||
|
||||
/* There are 4 layers of particles, specified as 0-3 by the method below. - Layer 0 causes the normal particles.png
|
||||
* to be bound to the render engine for normal particles. - Layer 1 causes the block textures to be bound to the
|
||||
* render engine for digging fx and falling fx. - Layer 2 causes the item textures to be bound to the render engine
|
||||
* for tool breaking fx, snowballpoofs, slime particles, etc. - Layer 3 is not used in vanilla minecraft and was
|
||||
* presumably added by forge for exactly this reason. This means no texture is bound by vanilla minecraft, meaning
|
||||
* you are free to do as you wish without possibly overwriting vanilla particles. Mod particles won't be overwritten
|
||||
* anyway since they bind their own textures. It is of course important to bind the texture every time you render a
|
||||
* custom particle, but I don't see how you could do it any other way, since you don't have access to
|
||||
* EffectRenderer. */
|
||||
@Override
|
||||
public int getFXLayer(){
|
||||
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ,
|
||||
float rotationYZ, float rotationXY, float rotationXZ){
|
||||
|
||||
// Copied from ParticleWizardry, needs to be here since we're not calling super
|
||||
updateEntityLinking(partialTicks);
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.pushAttrib();
|
||||
|
||||
float scale = 0.6f;
|
||||
GlStateManager.scale(scale, scale, scale);
|
||||
if(mirror) GlStateManager.scale(-1, 1, 1);
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableAlpha();
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.disableLighting();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE);
|
||||
// Makes the particle colour add to the colour of the texture pixels, rather than the default multiplying
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_ADD);
|
||||
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
|
||||
// Does the texture translation wrapping thing (the cool stuff)
|
||||
// GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
// GlStateManager.loadIdentity();
|
||||
//
|
||||
// GlStateManager.translate((this.particleAge + partialTicks)/(float)this.particleMaxAge * -2, 0, 0);
|
||||
//
|
||||
// GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
|
||||
Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
|
||||
|
||||
buffer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR);
|
||||
|
||||
float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
|
||||
float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
|
||||
float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
|
||||
|
||||
// Increases from 0 to 1 in steps of 0.125 evenly throughout the particle's lifetime
|
||||
float f = 0.125f * MathHelper.floor((float)this.particleAge/(float)this.particleMaxAge * 8 - 0.000001f);
|
||||
float g = f + 0.125f;
|
||||
float hrepeat = 1;
|
||||
float yScale = 3f;
|
||||
|
||||
this.setRBGColorF(1, 1, 1);
|
||||
|
||||
buffer.pos(x-1, y, z-1).tex(0, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x-1, y+yScale, z-1).tex(0, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x+1, y, z-1).tex(0.25*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x+1, y+yScale, z-1).tex(0.25*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x+1, y, z+1).tex(0.5*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x+1, y+yScale, z+1).tex(0.5*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x-1, y, z+1).tex(0.75*hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x-1, y+yScale, z+1).tex(0.75*hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x-1, y, z-1).tex(hrepeat, g).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
buffer.pos(x-1, y+yScale, z-1).tex(hrepeat, f).color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
|
||||
|
||||
Tessellator.getInstance().draw();
|
||||
|
||||
// Undoes the texture transformations
|
||||
// GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
// GlStateManager.loadIdentity();
|
||||
// GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.enableCull();
|
||||
GlStateManager.enableLighting();
|
||||
// Reverses the colour addition change from before
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||
|
||||
GlStateManager.popAttrib();
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package electroblob.wizardry.client.particle;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
@@ -15,6 +16,8 @@ import javax.annotation.Nullable;
|
||||
/** Superclass for particles with a second target entity or target position. */
|
||||
public abstract class ParticleTargeted extends ParticleWizardry {
|
||||
|
||||
private static final double THIRD_PERSON_AXIAL_OFFSET = 1.2;
|
||||
|
||||
protected double targetX;
|
||||
protected double targetY;
|
||||
protected double targetZ;
|
||||
@@ -73,16 +76,26 @@ public abstract class ParticleTargeted extends ParticleWizardry {
|
||||
float rotationXY, float rotationXZ){
|
||||
|
||||
// Copied from ParticleWizardry, needs to be here since we're not calling super
|
||||
updateEntityLinking(partialTicks);
|
||||
updateEntityLinking(viewer, partialTicks);
|
||||
|
||||
float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks);
|
||||
float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks);
|
||||
float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks);
|
||||
|
||||
// Translates the particle a short distance in front of the entity
|
||||
if(this.entity != null && this.shouldApplyOriginOffset()){
|
||||
if(this.entity != viewer || Minecraft.getMinecraft().gameSettings.thirdPersonView != 0){
|
||||
Vec3d look = entity.getLook(partialTicks).scale(THIRD_PERSON_AXIAL_OFFSET);
|
||||
x += look.x;
|
||||
y += look.y;
|
||||
z += look.z;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.target != null){
|
||||
|
||||
this.targetX = this.target.prevPosX + (this.target.posX - this.target.prevPosX) * partialTicks;
|
||||
double correction = this.target.getEntityBoundingBox().minY - this.target.posY;
|
||||
double correction = this.target.posY - this.target.posY;
|
||||
this.targetY = this.target.prevPosY + (this.target.posY - this.target.prevPosY) * partialTicks
|
||||
+ target.height/2 + correction;
|
||||
this.targetZ = this.target.prevPosZ + (this.target.posZ - this.target.prevPosZ) * partialTicks;
|
||||
@@ -133,6 +146,12 @@ public abstract class ParticleTargeted extends ParticleWizardry {
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
/** Returns whether the origin of this particle should be moved a short distance in front of the entity it is
|
||||
* linked to, if any. */
|
||||
protected boolean shouldApplyOriginOffset(){
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Called from {@link ParticleTargeted#renderParticle(BufferBuilder, Entity, float, float, float, float, float, float)},
|
||||
* once the appropriate calculations and transformations have been applied, to actually render the particle. Subclasses
|
||||
* override this <i>instead</i> of overriding {@code renderParticle} directly, and inside render the particle <b>along
|
||||
|
||||
@@ -46,6 +46,11 @@ public class ParticleVine extends ParticleTargeted {
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldApplyOriginOffset(){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void draw(Tessellator tessellator, double length, float partialTicks){
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package electroblob.wizardry.client.particle;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.ClientProxy;
|
||||
import electroblob.wizardry.entity.ICustomHitbox;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.particle.Particle;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
@@ -27,7 +27,7 @@ import java.util.stream.Collectors;
|
||||
/**
|
||||
* Abstract superclass for all of wizardry's particles. This replaces {@code ParticleCustomTexture} (the functionality of
|
||||
* which is no longer necessary since wizardry now uses {@code TextureAtlasSprite}s to do the rendering), and fits into
|
||||
* {@code ParticleBuilder} by exposing all the necessary variables through getters, allowing them to be set on the fly
|
||||
* {@code ParticleBuilder} by exposing all the necessary variables through setters, allowing them to be set on the fly
|
||||
* rather than needing to be passed into the constructor.
|
||||
* <p></p>
|
||||
* The new system is as follows:
|
||||
@@ -206,7 +206,7 @@ public abstract class ParticleWizardry extends Particle {
|
||||
this.entity = entity;
|
||||
// Set these to the correct values
|
||||
if(entity != null){
|
||||
this.setPosition(this.entity.posX + relativeX, this.entity.getEntityBoundingBox().minY
|
||||
this.setPosition(this.entity.posX + relativeX, this.entity.posY
|
||||
+ relativeY, this.entity.posZ + relativeZ);
|
||||
this.prevPosX = this.posX;
|
||||
this.prevPosY = this.posY;
|
||||
@@ -336,7 +336,7 @@ public abstract class ParticleWizardry extends Particle {
|
||||
public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float lookZ, float lookY,
|
||||
float lookX, float lookXY, float lookYZ){
|
||||
|
||||
updateEntityLinking(partialTicks);
|
||||
updateEntityLinking(viewer, partialTicks);
|
||||
|
||||
if(Float.isNaN(this.yaw) || Float.isNaN(this.pitch)){
|
||||
// Normal behaviour (rotates to face the viewer)
|
||||
@@ -369,12 +369,18 @@ public abstract class ParticleWizardry extends Particle {
|
||||
super.renderParticle(buffer, viewer, partialTicks, rotationX, rotationY, rotationZ, rotationYZ, rotationXY);
|
||||
}
|
||||
|
||||
protected void updateEntityLinking(float partialTicks){
|
||||
protected void updateEntityLinking(Entity viewer, float partialTicks){
|
||||
// TODO: Still not working, it seems this bug was a thing back in 4.2.x anyway
|
||||
if(this.entity != null){
|
||||
// This is kind of cheating but we know it's always a constant velocity so it works fine
|
||||
prevPosX = posX + entity.prevPosX - entity.posX - relativeMotionX * (1-partialTicks);
|
||||
prevPosY = posY + entity.prevPosY - entity.posY - relativeMotionY * (1-partialTicks);
|
||||
prevPosZ = posZ + entity.prevPosZ - entity.posZ - relativeMotionZ * (1-partialTicks);
|
||||
}else if(this.getFXLayer() == 3){
|
||||
// Not sure why, but when fx layer is 3, the interp pos is wrong when not linked to an entity
|
||||
interpPosX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * (double)partialTicks;
|
||||
interpPosY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * (double)partialTicks;
|
||||
interpPosZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * (double)partialTicks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,12 +473,12 @@ public abstract class ParticleWizardry extends Particle {
|
||||
|
||||
double searchRadius = 20;
|
||||
|
||||
List<Entity> nearbyEntities = WizardryUtilities.getEntitiesWithinRadius(searchRadius, this.posX,
|
||||
List<Entity> nearbyEntities = EntityUtils.getEntitiesWithinRadius(searchRadius, this.posX,
|
||||
this.posY, this.posZ, world, Entity.class);
|
||||
|
||||
nearbyEntities.removeIf(e -> !(e instanceof ICustomHitbox && ((ICustomHitbox)e).contains(new Vec3d(this.posX, this.posY, this.posZ))));
|
||||
|
||||
if(nearbyEntities.size() > 0) this.setExpired();
|
||||
if(nearbyEntities.stream().anyMatch(e -> e instanceof ICustomHitbox
|
||||
&& ((ICustomHitbox)e).calculateIntercept(new Vec3d(posX, posY, posZ),
|
||||
new Vec3d(prevPosX, prevPosY, prevPosZ), 0) != null)) this.setExpired();
|
||||
|
||||
}
|
||||
|
||||
@@ -547,7 +553,7 @@ public abstract class ParticleWizardry extends Particle {
|
||||
|
||||
/** Internal overload for {@link ParticleWizardry#generateTextures(String, String, int, int)} which uses wizardry's
|
||||
* mod ID automatically. */
|
||||
public static ResourceLocation[][] generateTextures(String stem, int m, int n){
|
||||
static ResourceLocation[][] generateTextures(String stem, int m, int n){
|
||||
return generateTextures(Wizardry.MODID, stem, m, n);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockStatue;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.client.model.ModelPlayer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.client.renderer.entity.RenderPlayer;
|
||||
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
/**
|
||||
* Layer used to render the frost texture on a creature with the frostbite effect. Handles dynamic tiling of the texture.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 1.2
|
||||
*/
|
||||
public class LayerFrost implements LayerRenderer<EntityLivingBase> {
|
||||
|
||||
protected ModelBase model;
|
||||
private final RenderLivingBase<?> renderer;
|
||||
|
||||
private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/entity/frost_overlay.png");
|
||||
|
||||
public static void initialiseLayers(){
|
||||
|
||||
for(Render<? extends Entity> renderer : Minecraft.getMinecraft().getRenderManager().entityRenderMap.values()){
|
||||
// Because the zombie classes are now split properly, their renderers play nicely like everything else.
|
||||
if(renderer instanceof RenderLivingBase){
|
||||
// Adds a frost layer to all the living entity renderers in the game. Whether it is actually rendered
|
||||
// is decided in doRenderLayer below on a per-entity basis.
|
||||
((RenderLivingBase<?>)renderer).addLayer(new LayerFrost((RenderLivingBase<?>)renderer));
|
||||
}
|
||||
}
|
||||
|
||||
for(RenderPlayer renderer : Minecraft.getMinecraft().getRenderManager().getSkinMap().values()){
|
||||
renderer.addLayer(new LayerFrost(renderer));
|
||||
}
|
||||
}
|
||||
|
||||
public LayerFrost(RenderLivingBase<?> renderer){
|
||||
this.renderer = renderer;
|
||||
this.model = renderer.getMainModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
if(entity.isPotionActive(WizardryPotions.frost) || entity.getEntityData().getBoolean(BlockStatue.FROZEN_NBT_KEY)){
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
int i = this.getBlockBrightnessForEntity(entity, partialTicks);
|
||||
|
||||
int j = i % 65536;
|
||||
int k = i / 65536;
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)j / 1.0F, (float)k / 1.0F);
|
||||
|
||||
// Frost texture
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
this.renderer.bindTexture(texture);
|
||||
this.renderEntityModel(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw,
|
||||
headPitch, scale);
|
||||
GlStateManager.disableBlend();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private int getBlockBrightnessForEntity(Entity entity, float partialTicks){
|
||||
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(MathHelper.floor(entity.posX), 0,
|
||||
MathHelper.floor(entity.posZ));
|
||||
|
||||
if(entity.world.isBlockLoaded(pos)){
|
||||
pos.setY(MathHelper.floor(entity.posY + (double)entity.getEyeHeight()));
|
||||
return entity.world.getCombinedLight(pos, 0);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void renderEntityModel(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
// Enables tiling (Also used for guardian beam, beacon beam and ender crystal beam)
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
|
||||
GlStateManager.depthMask(true); // Some entities set depth mask to false (i.e. no sorting of faces by depth)
|
||||
// In particular, LayerSpiderEyes sets it to false when the spider is invisible, for some reason.
|
||||
|
||||
// Changes the scale at which the texture is applied to the model. See LayerCreeper for a similar example,
|
||||
// but with translation instead of scaling.
|
||||
// NOTE: You can do all sorts of fun stuff with this, just by applying transformations in the 2D texture space.
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
GlStateManager.loadIdentity();
|
||||
double scaleX = 1, scaleY = 1;
|
||||
// It's more logical to use the model's texture size, but some classes don't bother setting it properly
|
||||
// (e.g. ModelVillager), so to get the correct dimensions I'm getting them from the first box instead.
|
||||
if(model.boxList != null && model.boxList.size() >= 1 && model.boxList.get(0) != null){
|
||||
scaleX = (double)model.boxList.get(0).textureWidth / 16d;
|
||||
scaleY = (double)model.boxList.get(0).textureHeight / 16d;
|
||||
}else{ // Fallback to model fields; should never be needed
|
||||
scaleX = (double)model.textureWidth / 16d;
|
||||
scaleY = (double)model.textureHeight / 16d;
|
||||
}
|
||||
GlStateManager.scale(scaleX, scaleY, 1);
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
boolean headWearHidden = false;
|
||||
boolean bodyWearHidden = false;
|
||||
boolean leftArmWearHidden = false;
|
||||
boolean rightArmWearHidden = false;
|
||||
boolean leftLegWearHidden = false;
|
||||
boolean rightLegWearHidden = false;
|
||||
|
||||
// Hides the hat layer for bipeds
|
||||
if(this.model instanceof ModelBiped){
|
||||
headWearHidden = ((ModelBiped)this.model).bipedHeadwear.isHidden;
|
||||
((ModelBiped)this.model).bipedHeadwear.isHidden = true;
|
||||
}
|
||||
|
||||
if(this.model instanceof ModelPlayer){
|
||||
bodyWearHidden = ((ModelPlayer)this.model).bipedBodyWear.isHidden;
|
||||
leftArmWearHidden = ((ModelPlayer)this.model).bipedLeftArmwear.isHidden;
|
||||
rightArmWearHidden = ((ModelPlayer)this.model).bipedRightArmwear.isHidden;
|
||||
leftLegWearHidden = ((ModelPlayer)this.model).bipedLeftLegwear.isHidden;
|
||||
rightLegWearHidden = ((ModelPlayer)this.model).bipedRightLegwear.isHidden;
|
||||
((ModelPlayer)this.model).bipedBodyWear.isHidden = true;
|
||||
((ModelPlayer)this.model).bipedLeftArmwear.isHidden = true;
|
||||
((ModelPlayer)this.model).bipedRightArmwear.isHidden = true;
|
||||
((ModelPlayer)this.model).bipedLeftLegwear.isHidden = true;
|
||||
((ModelPlayer)this.model).bipedRightLegwear.isHidden = true;
|
||||
}
|
||||
|
||||
this.model.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks);
|
||||
this.model.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
|
||||
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = headWearHidden;
|
||||
|
||||
if(this.model instanceof ModelPlayer){
|
||||
((ModelPlayer)this.model).bipedBodyWear.isHidden = bodyWearHidden;
|
||||
((ModelPlayer)this.model).bipedLeftArmwear.isHidden = leftArmWearHidden;
|
||||
((ModelPlayer)this.model).bipedRightArmwear.isHidden = rightArmWearHidden;
|
||||
((ModelPlayer)this.model).bipedLeftLegwear.isHidden = leftLegWearHidden;
|
||||
((ModelPlayer)this.model).bipedRightLegwear.isHidden = rightLegWearHidden;
|
||||
}
|
||||
|
||||
// Undoes the texture scaling
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
GlStateManager.loadIdentity();
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCombineTextures(){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
|
||||
import electroblob.wizardry.block.BlockStatue;
|
||||
import electroblob.wizardry.client.ClientProxy;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
/**
|
||||
* Layer used to render the stone texture on a petrified creature. Handles dynamic tiling of the stone texture.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 1.2
|
||||
*/
|
||||
public class LayerStone implements LayerRenderer<EntityLivingBase> {
|
||||
|
||||
protected ModelBase model;
|
||||
private final RenderLivingBase<?> renderer;
|
||||
|
||||
private static final ResourceLocation texture = new ResourceLocation("textures/blocks/stone.png");
|
||||
|
||||
public static void initialiseLayers(){
|
||||
|
||||
for(Render<? extends Entity> renderer : Minecraft.getMinecraft().getRenderManager().entityRenderMap.values()){
|
||||
// Because the zombie classes are now split properly, their renderers play nicely like everything else.
|
||||
if(renderer instanceof RenderLivingBase){
|
||||
// Adds a stone layer to all the living entity renderers in the game. Whether it is actually rendered
|
||||
// is decided in doRenderLayer below on a per-entity basis.
|
||||
((RenderLivingBase<?>)renderer).addLayer(new LayerStone((RenderLivingBase<?>)renderer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LayerStone(RenderLivingBase<?> renderer){
|
||||
this.renderer = renderer;
|
||||
this.model = renderer.getMainModel();
|
||||
}
|
||||
|
||||
// FIXME: Does not work with zombie pigmen, I have no idea why.
|
||||
// I believe the issue is with the TESR actually, since LayerFrost works fine
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
if(entity.getEntityData().getBoolean(BlockStatue.PETRIFIED_NBT_KEY)){
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
int i = this.getBlockBrightnessForEntity(entity, partialTicks);
|
||||
|
||||
int j = i % 65536;
|
||||
int k = i / 65536;
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)j / 1.0F, (float)k / 1.0F);
|
||||
|
||||
ResourceLocation breakingTexture = ClientProxy.renderStatue.getBlockBreakingTexture();
|
||||
|
||||
if(breakingTexture != null){
|
||||
// Block breaking animation
|
||||
// TODO: Spider eyes and enderman eyes (any others?) show through the stone when the block is being
|
||||
// broken...
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
this.renderer.bindTexture(breakingTexture);
|
||||
this.renderEntityModel(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw,
|
||||
headPitch, scale);
|
||||
GlStateManager.disableBlend();
|
||||
}else{
|
||||
// Stone texture
|
||||
this.renderer.bindTexture(texture);
|
||||
this.renderEntityModel(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw,
|
||||
headPitch, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getBlockBrightnessForEntity(Entity entity, float partialTicks){
|
||||
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(MathHelper.floor(entity.posX), 0,
|
||||
MathHelper.floor(entity.posZ));
|
||||
|
||||
if(entity.world.isBlockLoaded(pos)){
|
||||
pos.setY(MathHelper.floor(entity.posY + (double)entity.getEyeHeight()));
|
||||
return entity.world.getCombinedLight(pos, 0);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void renderEntityModel(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
// Enables tiling (Also used for guardian beam, beacon beam and ender crystal beam)
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
|
||||
GlStateManager.depthMask(true); // Some entities set depth mask to false (i.e. no sorting of faces by depth)
|
||||
// In particular, LayerSpiderEyes sets it to false when the spider is invisible, for some reason.
|
||||
|
||||
// Changes the scale at which the texture is applied to the model. See LayerCreeper for a similar example,
|
||||
// but with translation instead of scaling.
|
||||
// NOTE: You can do all sorts of fun stuff with this, just by applying transformations in the 2D texture space.
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
GlStateManager.loadIdentity();
|
||||
double scaleX = 1, scaleY = 1;
|
||||
// It's more logical to use the model's texture size, but some classes don't bother setting it properly
|
||||
// (e.g. ModelVillager), so to get the correct dimensions I'm getting them from the first box instead.
|
||||
if(model.boxList != null && model.boxList.get(0) != null){
|
||||
scaleX = (double)model.boxList.get(0).textureWidth / 16d;
|
||||
scaleY = (double)model.boxList.get(0).textureHeight / 16d;
|
||||
}else{ // Fallback to model fields; should never be needed
|
||||
scaleX = (double)model.textureWidth / 16d;
|
||||
scaleY = (double)model.textureHeight / 16d;
|
||||
}
|
||||
GlStateManager.scale(scaleX, scaleY, 1);
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
// Hides the hat layer for bipeds
|
||||
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = true;
|
||||
|
||||
this.model.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks);
|
||||
this.model.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
|
||||
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = false;
|
||||
|
||||
// Undoes the texture scaling
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
GlStateManager.loadIdentity();
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCombineTextures(){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
|
||||
/** Instances of this class can calculate their distance from the camera viewpoint and sort themselves accordingly. */
|
||||
class RayHelper implements Comparable<RayHelper> {
|
||||
public class RayHelper implements Comparable<RayHelper> {
|
||||
|
||||
int ordinal;
|
||||
double x1, y1, z1;
|
||||
double x2, y2, z2;
|
||||
public double x1, y1, z1;
|
||||
public double x2, y2, z2;
|
||||
double offsetX, offsetY, offsetZ;
|
||||
|
||||
RayHelper(int ordinal, double x1, double y1, double z1, double x2, double y2, double z2, double offsetX,
|
||||
public RayHelper(int ordinal, double x1, double y1, double z1, double x2, double y2, double z2, double offsetX,
|
||||
double offsetY, double offsetZ){
|
||||
this.ordinal = ordinal;
|
||||
this.x1 = x1;
|
||||
@@ -37,13 +37,7 @@ class RayHelper implements Comparable<RayHelper> {
|
||||
|
||||
@Override
|
||||
public int compareTo(RayHelper ray){
|
||||
if(this.getDistanceFromViewpoint() > ray.getDistanceFromViewpoint()){
|
||||
return -1;
|
||||
}else if(this.getDistanceFromViewpoint() < ray.getDistanceFromViewpoint()){
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
return Double.compare(ray.getDistanceFromViewpoint(), this.getDistanceFromViewpoint());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
|
||||
import electroblob.wizardry.entity.construct.EntityFireRing;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class RenderFireRing extends Render<EntityFireRing> {
|
||||
|
||||
private final ResourceLocation texture;
|
||||
private float scale = 1.0f;
|
||||
|
||||
public RenderFireRing(RenderManager renderManager, ResourceLocation texture, float scale){
|
||||
super(renderManager);
|
||||
this.texture = texture;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityFireRing entity, double par2, double par4, double par6, float par8, float par9){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
float yOffset = 0;
|
||||
|
||||
GlStateManager.translate((float)par2, (float)par4 + yOffset, (float)par6);
|
||||
|
||||
this.bindTexture(texture);
|
||||
float f6 = 1.0F;
|
||||
float f7 = 0.5F;
|
||||
float f8 = 0.5F;
|
||||
|
||||
GlStateManager.rotate(-90, 1, 0, 0);
|
||||
|
||||
GlStateManager.scale(scale, scale, scale);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
buffer.pos((double)(0.0F - f7), (double)(0.0F - f8), 0.01).tex(0, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(0.0F - f8), 0.01).tex(1, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(1.0F - f8), 0.01).tex(1, 0).endVertex();
|
||||
buffer.pos((double)(0.0F - f7), (double)(1.0F - f8), 0.01).tex(0, 0).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.disableRescaleNormal();
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
// Fire
|
||||
|
||||
GlStateManager.disableLighting();
|
||||
TextureAtlasSprite icon = Minecraft.getMinecraft().getBlockRendererDispatcher()
|
||||
.getModelForState(Blocks.FIRE.getDefaultState()).getParticleTexture();
|
||||
int sides = 16;
|
||||
float height = 1.0f;
|
||||
|
||||
for(int k = 0; k < sides; k++){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate((float)par2, (float)par4 + 0.05f, (float)par6);
|
||||
float f1 = 1.0f;
|
||||
GlStateManager.scale(f1, f1, f1);
|
||||
float f2 = 0.5F;
|
||||
float f3 = 0.0F;
|
||||
float f4 = 0.2f;
|
||||
float f5 = (float)(entity.posY - entity.getEntityBoundingBox().minY);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
float f61 = 0.0F;
|
||||
int i = 0;
|
||||
|
||||
GlStateManager.rotate((360f / (float)sides) * k, 0, 1, 0);
|
||||
GlStateManager.translate(0, 0, -2.3f);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
while(f4 > 0.0F){
|
||||
|
||||
this.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
|
||||
float f71 = icon.getMinU();
|
||||
float f81 = icon.getMinV();
|
||||
float f9 = icon.getMaxU();
|
||||
float f10 = icon.getMaxV();
|
||||
|
||||
if(i / 2 % 2 == 0){
|
||||
float f11 = f9;
|
||||
f9 = f71;
|
||||
f71 = f11;
|
||||
}
|
||||
|
||||
buffer.pos((double)(f2 - f3), (double)(0.0F - f5), (double)f61).tex((double)f9, (double)f10)
|
||||
.endVertex();
|
||||
buffer.pos((double)(-f2 - f3), (double)(0.0F - f5), (double)f61).tex((double)f71, (double)f10)
|
||||
.endVertex();
|
||||
buffer.pos((double)(-f2 - f3), (double)(height - f5), (double)f61).tex((double)f71, (double)f81)
|
||||
.endVertex();
|
||||
buffer.pos((double)(f2 - f3), (double)(height - f5), (double)f61).tex((double)f9, (double)f81)
|
||||
.endVertex();
|
||||
f4 -= 0.45F;
|
||||
f5 -= 0.45F;
|
||||
f2 *= 0.9F;
|
||||
f61 += 0.03F;
|
||||
++i;
|
||||
}
|
||||
|
||||
tessellator.draw();
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
for(int k = 0; k < sides; k++){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate((float)par2, (float)par4 + 0.05f, (float)par6);
|
||||
float f1 = 1.0f;
|
||||
GlStateManager.scale(f1, f1, f1);
|
||||
float f2 = 0.5F;
|
||||
float f3 = 0.0F;
|
||||
float f4 = 0.2f;
|
||||
float f5 = (float)(entity.posY - entity.getEntityBoundingBox().minY);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
float f61 = 0.0F;
|
||||
int i = 0;
|
||||
|
||||
GlStateManager.rotate((360f / (float)sides) * k, 0, 1, 0);
|
||||
GlStateManager.translate(0, 0, 2.3f);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
while(f4 > 0.0F){
|
||||
|
||||
this.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
|
||||
float f71 = icon.getMinU();
|
||||
float f81 = icon.getMinV();
|
||||
float f9 = icon.getMaxU();
|
||||
float f10 = icon.getMaxV();
|
||||
|
||||
if(i / 2 % 2 == 0){
|
||||
float f11 = f9;
|
||||
f9 = f71;
|
||||
f71 = f11;
|
||||
}
|
||||
|
||||
buffer.pos((double)(f2 - f3), (double)(0.0F - f5), (double)f61).tex((double)f9, (double)f10)
|
||||
.endVertex();
|
||||
buffer.pos((double)(-f2 - f3), (double)(0.0F - f5), (double)f61).tex((double)f71, (double)f10)
|
||||
.endVertex();
|
||||
buffer.pos((double)(-f2 - f3), (double)(height - f5), (double)f61).tex((double)f71, (double)f81)
|
||||
.endVertex();
|
||||
buffer.pos((double)(f2 - f3), (double)(height - f5), (double)f61).tex((double)f9, (double)f81)
|
||||
.endVertex();
|
||||
f4 -= 0.45F;
|
||||
f5 -= 0.45F;
|
||||
f2 *= 0.9F;
|
||||
f61 += 0.03F;
|
||||
++i;
|
||||
}
|
||||
|
||||
tessellator.draw();
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityFireRing entity){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+7
-27
@@ -1,9 +1,9 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.effect;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.potion.PotionContainment;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -24,14 +24,14 @@ import org.lwjgl.opengl.GL11;
|
||||
@Mod.EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderContainmentField {
|
||||
|
||||
private static final ResourceLocation[] textures = new ResourceLocation[8];
|
||||
private static final ResourceLocation[] TEXTURES = new ResourceLocation[8];
|
||||
|
||||
private static final float ANIMATION_SPEED = 0.004f;
|
||||
private static final float FADE_DISTANCE_SQUARED = 15;
|
||||
|
||||
static {
|
||||
for(int i=0; i<textures.length; i++){
|
||||
textures[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/containment_field_" + i + ".png");
|
||||
for(int i = 0; i< TEXTURES.length; i++){
|
||||
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/environment/containment_field_" + i + ".png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class RenderContainmentField {
|
||||
|
||||
if(player.isPotionActive(WizardryPotions.containment)){
|
||||
|
||||
Vec3d centre = WizardryUtilities.getCentre(NBTUtil.getPosFromTag(player.getEntityData().getCompoundTag(PotionContainment.ENTITY_TAG)));
|
||||
Vec3d centre = GeometryUtils.getCentre(NBTUtil.getPosFromTag(player.getEntityData().getCompoundTag(PotionContainment.ENTITY_TAG)));
|
||||
float r = PotionContainment.getContainmentDistance(player.getActivePotionEffect(WizardryPotions.containment).getAmplifier());
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
@@ -65,7 +65,7 @@ public class RenderContainmentField {
|
||||
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(textures[(player.ticksExisted % (textures.length * 2))/2]);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURES[(player.ticksExisted % (TEXTURES.length * 2))/2]);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
|
||||
@@ -245,24 +245,4 @@ public class RenderContainmentField {
|
||||
buffer.pos(x, y, z).tex(u, v).color(1, 1, 1, f * alpha).endVertex();
|
||||
}
|
||||
|
||||
// Useful to keep this mapping in case I ever want to draw cubes again
|
||||
|
||||
// Vec3d[] vertices = WizardryUtilities.getVertices(entity.getEntityBoundingBox().offset(entity.getPositionVector().scale(-1)));
|
||||
//
|
||||
// // Outside
|
||||
// drawFace(tessellator, vertices[0], vertices[1], vertices[3], vertices[2], u1, v1, u2, v2); // Bottom
|
||||
// drawFace(tessellator, vertices[6], vertices[7], vertices[2], vertices[3], u1, v1, u2, v2); // South
|
||||
// drawFace(tessellator, vertices[5], vertices[6], vertices[1], vertices[2], u1, v1, u2, v2); // East
|
||||
// drawFace(tessellator, vertices[4], vertices[5], vertices[0], vertices[1], u1, v1, u2, v2); // North
|
||||
// drawFace(tessellator, vertices[7], vertices[4], vertices[3], vertices[0], u1, v1, u2, v2); // West
|
||||
// drawFace(tessellator, vertices[5], vertices[4], vertices[6], vertices[7], u1, v1, u2, v2); // Top
|
||||
//
|
||||
// // Inside
|
||||
// drawFace(tessellator, vertices[1], vertices[0], vertices[2], vertices[3], u1, v1, u2, v2); // Bottom
|
||||
// drawFace(tessellator, vertices[7], vertices[6], vertices[3], vertices[2], u1, v1, u2, v2); // South
|
||||
// drawFace(tessellator, vertices[6], vertices[5], vertices[2], vertices[1], u1, v1, u2, v2); // East
|
||||
// drawFace(tessellator, vertices[5], vertices[4], vertices[1], vertices[0], u1, v1, u2, v2); // North
|
||||
// drawFace(tessellator, vertices[4], vertices[7], vertices[0], vertices[3], u1, v1, u2, v2); // West
|
||||
// drawFace(tessellator, vertices[4], vertices[5], vertices[7], vertices[6], u1, v1, u2, v2); // Top
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package electroblob.wizardry.client.renderer.effect;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockReceptacle;
|
||||
import electroblob.wizardry.constants.Element;
|
||||
import electroblob.wizardry.misc.DonationPerksHandler;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderDonationPerks {
|
||||
|
||||
private static final ResourceLocation FLARE_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/flare.png");
|
||||
private static final ResourceLocation[] CUBE_TEXTURES = new ResourceLocation[14];
|
||||
|
||||
private static final float BOBBING_PERIOD = 25;
|
||||
private static final float ROTATION_PERIOD = 60;
|
||||
private static final double ROTATION_RADIUS = 0.7;
|
||||
private static final double HEIGHT_FRACTION = 0.8;
|
||||
private static final double BOBBING_DISTANCE = 0.2;
|
||||
private static final double FOLLOW_DISTANCE = 1.4;
|
||||
|
||||
static {
|
||||
for(int i = 0; i< CUBE_TEXTURES.length; i++) CUBE_TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/cube_" + i + ".png");
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderPlayerEvent(RenderPlayerEvent.Post event){
|
||||
|
||||
EntityPlayer player = event.getEntityPlayer();
|
||||
float partialTicks = event.getPartialRenderTick();
|
||||
|
||||
Element element = DonationPerksHandler.getElement(player);
|
||||
|
||||
if(element != null){
|
||||
|
||||
int c1 = BlockReceptacle.PARTICLE_COLOURS.get(element)[0];
|
||||
int r1 = (c1 & 0xFF0000) >> 16;
|
||||
int g1 = (c1 & 0xFF00) >> 8;
|
||||
int b1 = (c1 & 0xFF);
|
||||
|
||||
int c2 = BlockReceptacle.PARTICLE_COLOURS.get(element)[2];
|
||||
int r2 = (c2 & 0xFF0000) >> 16;
|
||||
int g2 = (c2 & 0xFF00) >> 8;
|
||||
int b2 = (c2 & 0xFF);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
GlStateManager.depthMask(false);
|
||||
GlStateManager.disableCull();
|
||||
|
||||
double x1 = player.chasingPosX - player.posX;
|
||||
double y1 = player.chasingPosY - player.posY;
|
||||
double z1 = player.chasingPosZ - player.posZ;
|
||||
|
||||
double x2 = player.prevChasingPosX - player.prevPosX;
|
||||
double y2 = player.prevChasingPosY - player.prevPosY;
|
||||
double z2 = player.prevChasingPosZ - player.prevPosZ;
|
||||
|
||||
double dx = x2 + (x1 - x2) * partialTicks;
|
||||
double dy = y2 + (y1 - y2) * partialTicks;
|
||||
double dz = z2 + (z1 - z2) * partialTicks;
|
||||
|
||||
float t = player.ticksExisted + partialTicks;
|
||||
float hMoveFraction = MathHelper.clamp((float)(dx * dx + dz * dz) / 0.3f, 0, 1);
|
||||
float vMoveFraction = MathHelper.clamp((float)(dy * dy) / 0.3f, 0, 1);
|
||||
|
||||
double x = event.getX() + ROTATION_RADIUS * MathHelper.sin(t / ROTATION_PERIOD) * (1 - hMoveFraction) + FOLLOW_DISTANCE * dx;
|
||||
double y = event.getY() + HEIGHT_FRACTION * player.height + BOBBING_DISTANCE * MathHelper.sin(t / BOBBING_PERIOD) * (1 - vMoveFraction) + FOLLOW_DISTANCE * dy;
|
||||
double z = event.getZ() + ROTATION_RADIUS * MathHelper.cos(t / ROTATION_PERIOD) * (1 - hMoveFraction) + FOLLOW_DISTANCE * dz;
|
||||
GlStateManager.translate(x, y, z);
|
||||
|
||||
GlStateManager.scale(0.4, 0.4, 0.4);
|
||||
|
||||
// Makes the colour add to the colour of the texture pixels, rather than the default multiplying
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_ADD);
|
||||
GlStateManager.color(r1/255f, g1/255f, b1/255f);
|
||||
drawFlare(tessellator);
|
||||
|
||||
// Reverses the colour addition change
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||
GlStateManager.color(r2/255f, g2/255f, b2/255f);
|
||||
drawCube(player, tessellator, partialTicks);
|
||||
|
||||
GlStateManager.color(1, 1, 1,1);
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableCull();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void drawFlare(Tessellator tessellator){
|
||||
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(FLARE_TEXTURE);
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = Minecraft.getMinecraft().gameSettings.thirdPersonView == 2
|
||||
? Minecraft.getMinecraft().getRenderManager().playerViewX
|
||||
: -Minecraft.getMinecraft().getRenderManager().playerViewX;
|
||||
GlStateManager.rotate(180.0F - Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
float r = 0.5f;
|
||||
|
||||
buffer.pos(-r, r, 0).tex(0, 0).endVertex();
|
||||
buffer.pos( r, r, 0).tex(1, 0).endVertex();
|
||||
buffer.pos( r, -r, 0).tex(1, 1).endVertex();
|
||||
buffer.pos(-r, -r, 0).tex(0, 1).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private static void drawCube(EntityPlayer player, Tessellator tessellator, float partialTicks){
|
||||
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
float age = player.ticksExisted + partialTicks;
|
||||
float rotationSpeed = 2;
|
||||
|
||||
GlStateManager.rotate(age * rotationSpeed/2, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(60.0F, 0.7071F, 0.0F, 0.7071F);
|
||||
GlStateManager.rotate(age * rotationSpeed, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
GlStateManager.scale(0.5, 0.5, 0.5);
|
||||
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(CUBE_TEXTURES[player.ticksExisted % CUBE_TEXTURES.length]);
|
||||
|
||||
Vec3d[] vertices = GeometryUtils.getVertices(new AxisAlignedBB(-0.5, -0.5, -0.5, 0.5, 0.5, 0.5));
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
// Outside
|
||||
drawFace(buffer, vertices[0], vertices[1], vertices[3], vertices[2], 0.5f, 0, 0.75f, 0.5f); // Bottom
|
||||
drawFace(buffer, vertices[6], vertices[7], vertices[2], vertices[3], 0.75f, 0.5f, 1, 1); // South
|
||||
drawFace(buffer, vertices[5], vertices[6], vertices[1], vertices[2], 0, 0.5f, 0.25f, 1); // East
|
||||
drawFace(buffer, vertices[4], vertices[5], vertices[0], vertices[1], 0.25f, 0.5f, 0.5f, 1); // North
|
||||
drawFace(buffer, vertices[7], vertices[4], vertices[3], vertices[0], 0.5f, 0.5f, 0.75f, 1); // West
|
||||
drawFace(buffer, vertices[5], vertices[4], vertices[6], vertices[7], 0.25f, 0, 0.5f, 0.5f); // Top
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private static void drawFace(BufferBuilder buffer, Vec3d topLeft, Vec3d topRight, Vec3d bottomLeft, Vec3d bottomRight, float u1, float v1, float u2, float v2){
|
||||
buffer.pos(topLeft.x, topLeft.y, topLeft.z).tex(u1, v1).endVertex();
|
||||
buffer.pos(topRight.x, topRight.y, topRight.z).tex(u2, v1).endVertex();
|
||||
buffer.pos(bottomRight.x, bottomRight.y, bottomRight.z).tex(u2, v2).endVertex();
|
||||
buffer.pos(bottomLeft.x, bottomLeft.y, bottomLeft.z).tex(u1, v2).endVertex();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package electroblob.wizardry.client.renderer.effect;
|
||||
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraftforge.client.event.RenderLivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderMirage {
|
||||
|
||||
private static final int BLINK_PERIOD_1 = 47; // Use two prime numbers to make it look as chaotic as possible
|
||||
private static final int BLINK_PERIOD_2 = 71;
|
||||
|
||||
private static final double MAX_OFFSET = 3;
|
||||
|
||||
private static final Random random = new Random(); // Seed will be set later
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Pre<?> event){
|
||||
if(event.getEntity().isPotionActive(WizardryPotions.mirage)){
|
||||
random.setSeed(event.getEntity().ticksExisted / BLINK_PERIOD_1
|
||||
+ event.getEntity().ticksExisted / BLINK_PERIOD_2);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE); // GhoOOoOostly OooOOOo00oOOo
|
||||
GlStateManager.color(1, 1, 1, 0.5f);
|
||||
GlStateManager.translate((random.nextDouble() * 2 - 1) * MAX_OFFSET,
|
||||
(random.nextDouble() * 2 - 1) * MAX_OFFSET, (random.nextDouble() * 2 - 1) * MAX_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Post<?> event){
|
||||
if(event.getEntity().isPotionActive(WizardryPotions.mirage)){
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
-10
@@ -1,8 +1,8 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.effect;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -11,7 +11,6 @@ import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
@@ -32,7 +31,7 @@ public class RenderShadowWard {
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
|
||||
if(WizardryUtilities.isCasting(player, Spells.shadow_ward)){
|
||||
if(EntityUtils.isCasting(player, Spells.shadow_ward)){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
@@ -52,7 +51,7 @@ public class RenderShadowWard {
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.translate(0, 0, 1.2);
|
||||
GlStateManager.rotate(player.world.getTotalWorldTime() * -2, 0, 0, 1);
|
||||
GlStateManager.rotate(player.ticksExisted * -2, 0, 0, 1);
|
||||
GlStateManager.scale(1.1, 1.1, 1.1);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
@@ -94,7 +93,7 @@ public class RenderShadowWard {
|
||||
|
||||
EntityPlayer player = event.getEntityPlayer();
|
||||
|
||||
if(WizardryUtilities.isCasting(player, Spells.shadow_ward)){
|
||||
if(EntityUtils.isCasting(player, Spells.shadow_ward)){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
@@ -103,9 +102,7 @@ public class RenderShadowWard {
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
|
||||
Vec3d delta = player.getPositionEyes(event.getPartialRenderTick())
|
||||
.subtract(Minecraft.getMinecraft().player.getPositionEyes(event.getPartialRenderTick()));
|
||||
GlStateManager.translate(delta.x, delta.y, delta.z);
|
||||
GlStateManager.translate(event.getX(), event.getY(), event.getZ());
|
||||
|
||||
GlStateManager.rotate(180, 0, 1, 0);
|
||||
GlStateManager.rotate(-player.renderYawOffset, 0, 1, 0);
|
||||
@@ -116,7 +113,7 @@ public class RenderShadowWard {
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.translate(0, 1.2, 0);
|
||||
GlStateManager.rotate(player.world.getTotalWorldTime() * -2, 0, 0, 1);
|
||||
GlStateManager.rotate(player.ticksExisted * -2, 0, 0, 1);
|
||||
GlStateManager.scale(1.1, 1.1, 1.1);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
+57
-10
@@ -1,10 +1,10 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.effect;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.Shield;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -13,7 +13,6 @@ import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
@@ -34,7 +33,7 @@ public class RenderShield {
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().player;
|
||||
|
||||
if(WizardData.get(player).getVariable(Shield.SHIELD_KEY) != null && WizardryUtilities.isCasting(player, Spells.shield)){
|
||||
if(WizardData.get(player).getVariable(Shield.SHIELD_KEY) != null && EntityUtils.isCasting(player, Spells.shield)){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
@@ -50,7 +49,25 @@ public class RenderShield {
|
||||
GlStateManager.rotate(-player.rotationYaw, 0, 1, 0);
|
||||
GlStateManager.rotate(player.rotationPitch, 1, 0, 0);
|
||||
|
||||
GlStateManager.translate(0, 0, 0.8);
|
||||
GlStateManager.translate(0, 0, 1);
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
// Changes the scale at which the texture is applied to the model. See LayerCreeper for a similar example,
|
||||
// but with translation instead of scaling.
|
||||
// You can do all sorts of fun stuff with this, just by applying transformations in the 2D texture space.
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE); // Switch to the 2D texture space
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
GlStateManager.translate(0.5, 0.5, 0);
|
||||
|
||||
float s = 1 - ((player.ticksExisted + event.getPartialTicks()) % 5) / 5 * 0.52f;
|
||||
s = s*s;
|
||||
GlStateManager.scale(s, s, 1);
|
||||
|
||||
GlStateManager.translate(-0.5, -0.5, 0);
|
||||
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW); // Switch back to the 3D model space
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
|
||||
@@ -58,6 +75,13 @@ public class RenderShield {
|
||||
|
||||
render(tessellator);
|
||||
|
||||
// Undo the texture scaling
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
GlStateManager.loadIdentity();
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
|
||||
GlStateManager.shadeModel(GL11.GL_FLAT);
|
||||
@@ -76,7 +100,7 @@ public class RenderShield {
|
||||
|
||||
EntityPlayer player = event.getEntityPlayer();
|
||||
|
||||
if(WizardData.get(player).getVariable(Shield.SHIELD_KEY) != null && WizardryUtilities.isCasting(player, Spells.shield)){
|
||||
if(WizardData.get(player).getVariable(Shield.SHIELD_KEY) != null && EntityUtils.isCasting(player, Spells.shield)){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
@@ -89,9 +113,7 @@ public class RenderShield {
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
|
||||
Vec3d delta = player.getPositionEyes(event.getPartialRenderTick())
|
||||
.subtract(Minecraft.getMinecraft().player.getPositionEyes(event.getPartialRenderTick()));
|
||||
GlStateManager.translate(delta.x, delta.y, delta.z);
|
||||
GlStateManager.translate(event.getX(), event.getY(), event.getZ());
|
||||
|
||||
GlStateManager.translate(0, 1.3, 0);
|
||||
|
||||
@@ -99,7 +121,25 @@ public class RenderShield {
|
||||
GlStateManager.rotate(-player.renderYawOffset, 0, 1, 0);
|
||||
// GlStateManager.rotate(-player.rotationPitch, 1, 0, 0);
|
||||
|
||||
GlStateManager.translate(0, 0, 0.8);
|
||||
GlStateManager.translate(0, 0, 1);
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
// Changes the scale at which the texture is applied to the model. See LayerCreeper for a similar example,
|
||||
// but with translation instead of scaling.
|
||||
// You can do all sorts of fun stuff with this, just by applying transformations in the 2D texture space.
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE); // Switch to the 2D texture space
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
GlStateManager.translate(0.5, 0.5, 0);
|
||||
|
||||
float s = 1 - ((player.ticksExisted + event.getPartialRenderTick()) % 5) / 5 * 0.52f;
|
||||
s = s*s;
|
||||
GlStateManager.scale(s, s, 1);
|
||||
|
||||
GlStateManager.translate(-0.5, -0.5, 0);
|
||||
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW); // Switch back to the 3D model space
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
|
||||
@@ -107,6 +147,13 @@ public class RenderShield {
|
||||
|
||||
render(tessellator);
|
||||
|
||||
// Undo the texture scaling
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
GlStateManager.loadIdentity();
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
|
||||
GlStateManager.shadeModel(GL11.GL_FLAT);
|
||||
+4
-7
@@ -1,8 +1,8 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.effect;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -12,7 +12,6 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
@@ -32,7 +31,7 @@ public class RenderWings {
|
||||
|
||||
EntityPlayer player = event.getEntityPlayer();
|
||||
|
||||
if(WizardryUtilities.isCasting(player, Spells.flight)){
|
||||
if(EntityUtils.isCasting(player, Spells.flight)){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
@@ -41,9 +40,7 @@ public class RenderWings {
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
|
||||
Vec3d delta = player.getPositionEyes(event.getPartialRenderTick())
|
||||
.subtract(Minecraft.getMinecraft().player.getPositionEyes(event.getPartialRenderTick()));
|
||||
GlStateManager.translate(delta.x, delta.y, delta.z);
|
||||
GlStateManager.translate(event.getX(), event.getY(), event.getZ());
|
||||
|
||||
// GlStateManager.rotate(-entityplayer.rotationYawHead, 0, 1, 0);
|
||||
GlStateManager.rotate(-player.renderYawOffset, 0, 1, 0);
|
||||
+22
-25
@@ -1,6 +1,8 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.client.renderer.RayHelper;
|
||||
import electroblob.wizardry.entity.construct.EntityBlackHole;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.*;
|
||||
@@ -16,17 +18,18 @@ import java.util.Collections;
|
||||
|
||||
public class RenderBlackHole extends Render<EntityBlackHole> {
|
||||
|
||||
private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID,
|
||||
"textures/entity/dark_ray.png");
|
||||
private static final ResourceLocation texture2 = new ResourceLocation(Wizardry.MODID,
|
||||
"textures/entity/black_hole.png");
|
||||
// TODO: Remove RayHelper and the ray texture entirely and use colours with depth mask off (like imbuement altar)
|
||||
private static final ResourceLocation RAY_TEXTURE = new ResourceLocation(Wizardry.MODID,
|
||||
"textures/entity/black_hole/ray.png");
|
||||
private static final ResourceLocation CENTRE_TEXTURE = new ResourceLocation(Wizardry.MODID,
|
||||
"textures/entity/black_hole/centre.png");
|
||||
|
||||
public RenderBlackHole(RenderManager renderManager){
|
||||
super(renderManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityBlackHole blackhole, double x, double y, double z, float fa, float fb){
|
||||
public void doRender(EntityBlackHole entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
@@ -48,16 +51,10 @@ public class RenderBlackHole extends Render<EntityBlackHole> {
|
||||
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
if(blackhole.ticksExisted < 10){
|
||||
GlStateManager.scale((float)blackhole.ticksExisted / 10, (float)blackhole.ticksExisted / 10,
|
||||
(float)blackhole.ticksExisted / 10);
|
||||
}
|
||||
if(blackhole.ticksExisted > blackhole.lifetime - 10){
|
||||
float scale = Math.max(0, (float)(blackhole.lifetime - blackhole.ticksExisted) / 10);
|
||||
GlStateManager.scale(scale, scale, scale);
|
||||
}
|
||||
float s = DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 10);
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
this.bindTexture(texture);
|
||||
this.bindTexture(RAY_TEXTURE);
|
||||
|
||||
// In theory this stuff should sort the rays into the correct render order based on the distance from
|
||||
// the 'camera' (i.e. the player's viewpoint)
|
||||
@@ -65,24 +62,24 @@ public class RenderBlackHole extends Render<EntityBlackHole> {
|
||||
// coordinates which were inconsistent with my calculated ones. Since I know those will give the desired
|
||||
// effect anyway, I just used them directly instead.
|
||||
|
||||
ArrayList<RayHelper> rays = new ArrayList<RayHelper>(1);
|
||||
ArrayList<RayHelper> rays = new ArrayList<>(1);
|
||||
|
||||
for(int j = 0; j < 30; j++){
|
||||
|
||||
float scale = 3.0f;
|
||||
float radius = 3.0f * entity.getSizeMultiplier();
|
||||
|
||||
int a = blackhole.randomiser[j];
|
||||
int b = blackhole.randomiser2[j];
|
||||
int a = entity.randomiser[j];
|
||||
int b = entity.randomiser2[j];
|
||||
|
||||
int sliceAngle = 20 + a;
|
||||
|
||||
double x1 = scale * MathHelper.sin((blackhole.ticksExisted + 40 * j) * ((float)Math.PI / 180f));
|
||||
double x1 = radius * MathHelper.sin((entity.ticksExisted + 40 * j) * ((float)Math.PI / 180f));
|
||||
// double y1 = 0.7*MathHelper.cos((blackhole.timer - 40*j)*(Math.PI/180))*j/10;
|
||||
double z1 = scale * MathHelper.cos((blackhole.ticksExisted + 40 * j) * ((float)Math.PI / 180));
|
||||
double z1 = radius * MathHelper.cos((entity.ticksExisted + 40 * j) * ((float)Math.PI / 180));
|
||||
|
||||
double x2 = scale * MathHelper.sin((blackhole.ticksExisted + 40 * j - sliceAngle) * ((float)Math.PI / 180));
|
||||
double x2 = radius * MathHelper.sin((entity.ticksExisted + 40 * j - sliceAngle) * ((float)Math.PI / 180));
|
||||
// double y2 = 0.7*MathHelper.sin((blackhole.timer - 40*j)*(Math.PI/180))*j/10;
|
||||
double z2 = scale * MathHelper.cos((blackhole.ticksExisted + 40 * j - sliceAngle) * ((float)Math.PI / 180));
|
||||
double z2 = radius * MathHelper.cos((entity.ticksExisted + 40 * j - sliceAngle) * ((float)Math.PI / 180));
|
||||
|
||||
double absoluteX = x1 * MathHelper.cos(31 * b);
|
||||
double absoluteY = z1 * MathHelper.sin(31 * a) + x1 * MathHelper.cos(31 * a) * MathHelper.sin(31 * b);
|
||||
@@ -142,7 +139,7 @@ public class RenderBlackHole extends Render<EntityBlackHole> {
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
this.bindTexture(texture2);
|
||||
this.bindTexture(CENTRE_TEXTURE);
|
||||
|
||||
buffer.pos(-0.4, 0.4, 0).tex(0, 0).endVertex();
|
||||
buffer.pos(0.4, 0.4, 0).tex(1, 0).endVertex();
|
||||
@@ -164,7 +161,7 @@ public class RenderBlackHole extends Render<EntityBlackHole> {
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityBlackHole entity){
|
||||
return texture;
|
||||
return RAY_TEXTURE;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
@@ -0,0 +1,51 @@
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.client.model.ModelBoulder;
|
||||
import electroblob.wizardry.entity.construct.EntityBoulder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class RenderBoulder extends Render<EntityBoulder> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/boulder.png");
|
||||
|
||||
private ModelBoulder model = new ModelBoulder();
|
||||
|
||||
public RenderBoulder(RenderManager manager){
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityBoulder entity, double x, double y, double z, float yaw, float partialTicks){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(x, y + entity.height/2, z);
|
||||
GlStateManager.rotate(180, 0F, 0F, 1F);
|
||||
GlStateManager.rotate(yaw - 90, 0, 1, 0);
|
||||
GlStateManager.rotate(entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * partialTicks, 0, 0, 1);
|
||||
GlStateManager.translate(0, -entity.height/2, 0);
|
||||
|
||||
// Pass in -1 for the lifetime as the boulder crumbles when the time expires
|
||||
float s = DrawingUtils.smoothScaleFactor(-1, entity.ticksExisted, partialTicks, 10, 10);
|
||||
s *= entity.getSizeMultiplier();
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
GlStateManager.translate(0, 0.875, 0); // No idea why it starts 7/8 of a block too low, but it does
|
||||
|
||||
this.bindTexture(TEXTURE);
|
||||
|
||||
model.render(entity, 0, 0, 0, 0, 0, 0.0625f);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityBoulder entity){
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
}
|
||||
+27
-27
@@ -1,8 +1,9 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.entity.construct.EntityBubble;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -11,21 +12,21 @@ import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class RenderBubble extends Render<EntityBubble> {
|
||||
|
||||
private static final ResourceLocation particleTextures = new ResourceLocation("textures/particle/particles.png");
|
||||
private static final ResourceLocation darkOrbTexture = new ResourceLocation(Wizardry.MODID,
|
||||
"textures/entity/dark_orb.png");
|
||||
private static final ResourceLocation PARTICLE_TEXTURES = new ResourceLocation("textures/particle/particles.png");
|
||||
private static final ResourceLocation ENTRAPMENT_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/entrapment.png");
|
||||
|
||||
public RenderBubble(RenderManager renderManager){
|
||||
super(renderManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityBubble entity, double par2, double par4, double par6, float par8, float par9){
|
||||
public void doRender(EntityBubble entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.enableBlend();
|
||||
@@ -33,18 +34,20 @@ public class RenderBubble extends Render<EntityBubble> {
|
||||
|
||||
float yOffset = 0;
|
||||
|
||||
if(WizardryUtilities.getRider(entity) != null){
|
||||
yOffset = WizardryUtilities.getRider(entity).height / 2;
|
||||
Entity rider = EntityUtils.getRider(entity);
|
||||
|
||||
if(rider != null){
|
||||
yOffset = rider.height / 2;
|
||||
}
|
||||
|
||||
GlStateManager.translate((float)par2, (float)par4 + yOffset, (float)par6);
|
||||
GlStateManager.translate((float)x, (float)y + yOffset, (float)z);
|
||||
|
||||
this.bindTexture(((EntityBubble)entity).isDarkOrb ? darkOrbTexture : particleTextures);
|
||||
this.bindTexture(entity.isDarkOrb ? ENTRAPMENT_TEXTURE : PARTICLE_TEXTURES);
|
||||
float f6 = 1.0F;
|
||||
float f7 = 0.5F;
|
||||
float f8 = 0.5F;
|
||||
|
||||
if(((EntityBubble)entity).isDarkOrb){
|
||||
if(entity.isDarkOrb){
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
}else{
|
||||
@@ -63,35 +66,32 @@ public class RenderBubble extends Render<EntityBubble> {
|
||||
GlStateManager.rotate(180.0F - this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
float f11 = 3.0F;
|
||||
GlStateManager.scale(f11, f11, f11);
|
||||
// Bubble 'bursts' so doesn't shrink when is disappears
|
||||
float s = 3 * DrawingUtils.smoothScaleFactor(entity.isDarkOrb ? entity.lifetime : -1, entity.ticksExisted, partialTicks, 10, 10);
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
double pixelwidth = (1.0d / 128);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
// tessellator.setColorRGBA_I(k1, 128);
|
||||
// buffer.normal(0.0F, 1.0F, 0.0F);
|
||||
|
||||
if(((EntityBubble)entity).isDarkOrb){
|
||||
buffer.pos((double)(0.0F - f7), (double)(0.0F - f8), 0.0D).tex(0, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(0.0F - f8), 0.0D).tex(1, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(1.0F - f8), 0.0D).tex(1, 0).endVertex();
|
||||
buffer.pos((double)(0.0F - f7), (double)(1.0F - f8), 0.0D).tex(0, 0).endVertex();
|
||||
if(entity.isDarkOrb){
|
||||
buffer.pos(0.0F - f7, 0.0F - f8, 0.0D).tex(0, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 0.0F - f8, 0.0D).tex(1, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 1.0F - f8, 0.0D).tex(1, 0).endVertex();
|
||||
buffer.pos(0.0F - f7, 1.0F - f8, 0.0D).tex(0, 0).endVertex();
|
||||
}else{
|
||||
buffer.pos((double)(0.0F - f7), (double)(0.0F - f8), 0.0D).tex(pixelwidth, pixelwidth * 24).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(0.0F - f8), 0.0D).tex(pixelwidth * 8, pixelwidth * 24).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(1.0F - f8), 0.0D).tex(pixelwidth * 8, pixelwidth * 17).endVertex();
|
||||
buffer.pos((double)(0.0F - f7), (double)(1.0F - f8), 0.0D).tex(pixelwidth, pixelwidth * 17).endVertex();
|
||||
buffer.pos(0.0F - f7, 0.0F - f8, 0.0D).tex(pixelwidth, pixelwidth * 24).endVertex();
|
||||
buffer.pos(f6 - f7, 0.0F - f8, 0.0D).tex(pixelwidth * 8, pixelwidth * 24).endVertex();
|
||||
buffer.pos(f6 - f7, 1.0F - f8, 0.0D).tex(pixelwidth * 8, pixelwidth * 17).endVertex();
|
||||
buffer.pos(0.0F - f7, 1.0F - f8, 0.0D).tex(pixelwidth, pixelwidth * 17).endVertex();
|
||||
}
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
if(((EntityBubble)entity).isDarkOrb){
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
if(entity.isDarkOrb) GlStateManager.enableLighting();
|
||||
GlStateManager.disableRescaleNormal();
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
+14
-15
@@ -1,6 +1,7 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.entity.construct.EntityDecay;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -14,17 +15,17 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class RenderDecay extends Render<EntityDecay> {
|
||||
|
||||
private static final ResourceLocation[] textures = new ResourceLocation[10];
|
||||
private static final ResourceLocation[] TEXTURES = new ResourceLocation[10];
|
||||
|
||||
public RenderDecay(RenderManager renderManager){
|
||||
super(renderManager);
|
||||
for(int i = 0; i < 10; i++){
|
||||
textures[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/decay_" + i + ".png");
|
||||
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/decay/decay_" + i + ".png");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityDecay entity, double par2, double par4, double par6, float par8, float par9){
|
||||
public void doRender(EntityDecay entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.enableBlend();
|
||||
@@ -34,28 +35,26 @@ public class RenderDecay extends Render<EntityDecay> {
|
||||
|
||||
float yOffset = 0;
|
||||
|
||||
GlStateManager.translate((float)par2, (float)par4 + yOffset, (float)par6);
|
||||
GlStateManager.translate((float)x, (float)y + yOffset, (float)z);
|
||||
|
||||
this.bindTexture(textures[((EntityDecay)entity).textureIndex]);
|
||||
this.bindTexture(TEXTURES[entity.textureIndex]);
|
||||
float f6 = 1.0F;
|
||||
float f7 = 0.5F;
|
||||
float f8 = 0.5F;
|
||||
|
||||
GlStateManager.rotate(-90, 1, 0, 0);
|
||||
|
||||
float scale = 2 * Math.min(1, (float)(entity.lifetime - entity.ticksExisted) / 50f);
|
||||
|
||||
GlStateManager.scale(scale, scale, scale);
|
||||
float s = 2 * DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 50);
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
// tessellator.setColorRGBA_I(k1, 128);
|
||||
// buffer.normal(0.0F, 1.0F, 0.0F);
|
||||
buffer.pos((double)(0.0F - f7), (double)(0.0F - f8), 0.01).tex(0, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(0.0F - f8), 0.01).tex(1, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(1.0F - f8), 0.01).tex(1, 0).endVertex();
|
||||
buffer.pos((double)(0.0F - f7), (double)(1.0F - f8), 0.01).tex(0, 0).endVertex();
|
||||
|
||||
buffer.pos(0.0F - f7, 0.0F - f8, 0.01).tex(0, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 0.0F - f8, 0.01).tex(1, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 1.0F - f8, 0.01).tex(1, 0).endVertex();
|
||||
buffer.pos(0.0F - f7, 1.0F - f8, 0.01).tex(0, 0).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.entity.living.EntityDecoy;
|
||||
@@ -8,7 +8,7 @@ import net.minecraft.client.renderer.entity.RenderBiped;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.relauncher.ReflectionHelper;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -18,8 +18,8 @@ public class RenderDecoy extends RenderBiped<EntityDecoy> {
|
||||
|
||||
private static final ResourceLocation steveTextures = new ResourceLocation("textures/entity/steve.png");
|
||||
|
||||
private static final Method getEntityTexture = ReflectionHelper.findMethod(Render.class, "getEntityTexture",
|
||||
"func_110775_a", Entity.class); // Generic parameter T is erased to Entity at runtime.
|
||||
private static final Method getEntityTexture = ObfuscationReflectionHelper.findMethod(Render.class, "func_110775_a",
|
||||
ResourceLocation.class, Entity.class); // Generic parameter T is erased to Entity at runtime.
|
||||
|
||||
public RenderDecoy(RenderManager manager){
|
||||
super(manager, new ModelBiped(0.0f), 0.5f);
|
||||
+5
-4
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.model.ModelWizard;
|
||||
@@ -10,14 +10,15 @@ import net.minecraft.util.ResourceLocation;
|
||||
|
||||
//@SideOnly(Side.CLIENT)
|
||||
public class RenderEvilWizard extends RenderBiped<EntityEvilWizard> {
|
||||
static final ResourceLocation[] textures = new ResourceLocation[6];
|
||||
|
||||
static final ResourceLocation[] TEXTURES = new ResourceLocation[6];
|
||||
|
||||
public RenderEvilWizard(RenderManager renderManager){
|
||||
|
||||
super(renderManager, new ModelWizard(), 0.5F);
|
||||
|
||||
for(int i = 0; i < 6; i++){
|
||||
textures[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/evil_wizard_" + i + ".png");
|
||||
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/evil_wizard/evil_wizard_" + i + ".png");
|
||||
}
|
||||
// Just using the default without overriding models, since the armour sets its own model anyway.
|
||||
this.addLayer(new LayerBipedArmor(this));
|
||||
@@ -25,7 +26,7 @@ public class RenderEvilWizard extends RenderBiped<EntityEvilWizard> {
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityEvilWizard wizard){
|
||||
return textures[wizard.textureIndex];
|
||||
return TEXTURES[wizard.textureIndex];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.entity.construct.EntityFireRing;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class RenderFireRing extends Render<EntityFireRing> {
|
||||
|
||||
private final ResourceLocation texture;
|
||||
|
||||
public RenderFireRing(RenderManager renderManager, ResourceLocation texture){
|
||||
super(renderManager);
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityFireRing entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
float yOffset = 0;
|
||||
|
||||
GlStateManager.translate(x, y + yOffset, z);
|
||||
|
||||
this.bindTexture(texture);
|
||||
float f6 = 1.0F;
|
||||
float f7 = 0.5F;
|
||||
float f8 = 0.5F;
|
||||
|
||||
GlStateManager.rotate(-90, 1, 0, 0);
|
||||
|
||||
float s = DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 10);
|
||||
GlStateManager.scale(entity.width * s, entity.width * s, entity.width * s);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
buffer.pos(0.0F - f7, 0.0F - f8, 0.01).tex(0, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 0.0F - f8, 0.01).tex(1, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 1.0F - f8, 0.01).tex(1, 0).endVertex();
|
||||
buffer.pos(0.0F - f7, 1.0F - f8, 0.01).tex(0, 0).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.disableRescaleNormal();
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
// Fire
|
||||
// TODO: Bleeeuuurugh this is disgusting must fix :0
|
||||
|
||||
if(s >= 1){
|
||||
GlStateManager.disableLighting();
|
||||
TextureAtlasSprite icon = Minecraft.getMinecraft().getBlockRendererDispatcher()
|
||||
.getModelForState(Blocks.FIRE.getDefaultState()).getParticleTexture();
|
||||
float s1 = entity.width/5;
|
||||
int sides = (int)(16 * s1);
|
||||
float height = 1.0f;
|
||||
|
||||
for(int k = 0; k < sides; k++){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate((float)x, (float)y + 0.05f, (float)z);
|
||||
// GlStateManager.scale(s1, s1, s1);
|
||||
float f2 = 0.5F;
|
||||
float f3 = 0.0F;
|
||||
float f4 = 0.2f;
|
||||
float f5 = (float)(entity.posY - entity.posY);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
float f61 = 0.0F;
|
||||
int i = 0;
|
||||
|
||||
GlStateManager.rotate((360f / (float)sides) * k, 0, 1, 0);
|
||||
GlStateManager.translate(0, 0, -2.3f * s1);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
while(f4 > 0.0F){
|
||||
|
||||
this.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
|
||||
float f71 = icon.getMinU();
|
||||
float f81 = icon.getMinV();
|
||||
float f9 = icon.getMaxU();
|
||||
float f10 = icon.getMaxV();
|
||||
|
||||
if(i / 2 % 2 == 0){
|
||||
float f11 = f9;
|
||||
f9 = f71;
|
||||
f71 = f11;
|
||||
}
|
||||
|
||||
buffer.pos((f2 - f3), (0.0F - f5), f61).tex(f9, f10).endVertex();
|
||||
buffer.pos((-f2 - f3), (0.0F - f5), f61).tex(f71, f10).endVertex();
|
||||
buffer.pos((-f2 - f3), (height - f5), f61).tex(f71, f81).endVertex();
|
||||
buffer.pos((f2 - f3), (height - f5), f61).tex(f9, f81).endVertex();
|
||||
f4 -= 0.45F;
|
||||
f5 -= 0.45F;
|
||||
f2 *= 0.9F;
|
||||
f61 += 0.03F;
|
||||
++i;
|
||||
}
|
||||
|
||||
tessellator.draw();
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
for(int k = 0; k < sides; k++){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate((float)x, (float)y + 0.05f, (float)z);
|
||||
// GlStateManager.scale(s1, s1, s1);
|
||||
float f2 = 0.5F;
|
||||
float f3 = 0.0F;
|
||||
float f4 = 0.2f;
|
||||
float f5 = (float)(entity.posY - entity.posY);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
float f61 = 0.0F;
|
||||
int i = 0;
|
||||
|
||||
GlStateManager.rotate((360f / (float)sides) * k, 0, 1, 0);
|
||||
GlStateManager.translate(0, 0, 2.3f * s1);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
while(f4 > 0.0F){
|
||||
|
||||
this.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
|
||||
float f71 = icon.getMinU();
|
||||
float f81 = icon.getMinV();
|
||||
float f9 = icon.getMaxU();
|
||||
float f10 = icon.getMaxV();
|
||||
|
||||
if(i / 2 % 2 == 0){
|
||||
float f11 = f9;
|
||||
f9 = f71;
|
||||
f71 = f11;
|
||||
}
|
||||
|
||||
buffer.pos((f2 - f3), (0.0F - f5), f61).tex(f9, f10).endVertex();
|
||||
buffer.pos((-f2 - f3), (0.0F - f5), f61).tex(f71, f10).endVertex();
|
||||
buffer.pos((-f2 - f3), (height - f5), f61).tex(f71, f81).endVertex();
|
||||
buffer.pos((f2 - f3), (height - f5), f61).tex(f9, f81).endVertex();
|
||||
f4 -= 0.45F;
|
||||
f5 -= 0.45F;
|
||||
f2 *= 0.9F;
|
||||
f61 += 0.03F;
|
||||
++i;
|
||||
}
|
||||
|
||||
tessellator.draw();
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityFireRing entity){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.entity.projectile.EntityForceArrow;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.entity.construct.EntityForcefield;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.model.ModelHammer;
|
||||
@@ -0,0 +1,45 @@
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.model.ModelIceBarrier;
|
||||
import electroblob.wizardry.entity.construct.EntityIceBarrier;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class RenderIceBarrier extends Render<EntityIceBarrier> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/ice_barrier.png");
|
||||
|
||||
private ModelIceBarrier model = new ModelIceBarrier();
|
||||
|
||||
public RenderIceBarrier(RenderManager manager){
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityIceBarrier entity, double x, double y, double z, float yaw, float partialTicks){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(x, y + entity.height/2, z);
|
||||
GlStateManager.rotate(180, 0F, 0F, 1F);
|
||||
GlStateManager.rotate(yaw, 0, 1, 0);
|
||||
GlStateManager.translate(0, -entity.height/2 - 0.3, 0);
|
||||
|
||||
float s = entity.getSizeMultiplier();
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
this.bindTexture(TEXTURE);
|
||||
|
||||
model.render(entity, 0, 0, 0, 0, 0, 0.0625f);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityIceBarrier entity){
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.model.ModelIceGiant;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.entity.construct.EntityIceSpike;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.entity.projectile.EntityLightningDisc;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.entity.projectile.EntityMagicArrow;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.model.ModelPhoenix;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.spell.Possession;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.entity.projectile.EntityMagicProjectile;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -0,0 +1,151 @@
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.entity.construct.EntityRadiantTotem;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RenderRadiantTotem extends Render<EntityRadiantTotem> {
|
||||
|
||||
private static final ResourceLocation FLARE_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/flare.png");
|
||||
private static final ResourceLocation[] CUBE_TEXTURES = new ResourceLocation[14];
|
||||
|
||||
static {
|
||||
for(int i = 0; i< CUBE_TEXTURES.length; i++) CUBE_TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/cube_" + i + ".png");
|
||||
}
|
||||
|
||||
public RenderRadiantTotem(RenderManager manager){
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityRadiantTotem entity){
|
||||
return CUBE_TEXTURES[entity.ticksExisted % CUBE_TEXTURES.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityRadiantTotem entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
GlStateManager.depthMask(false);
|
||||
GlStateManager.disableCull();
|
||||
|
||||
GlStateManager.translate(x, y + entity.height/2, z);
|
||||
|
||||
float s = DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 10);
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
drawFlare(tessellator);
|
||||
drawCube(entity, tessellator, partialTicks);
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableCull();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private void drawFlare(Tessellator tessellator){
|
||||
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
// Makes the colour add to the colour of the texture pixels, rather than the default multiplying
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_ADD);
|
||||
GlStateManager.color(1, 0.957f, 0.608f);
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
bindTexture(FLARE_TEXTURE);
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = Minecraft.getMinecraft().gameSettings.thirdPersonView == 2
|
||||
? Minecraft.getMinecraft().getRenderManager().playerViewX
|
||||
: -Minecraft.getMinecraft().getRenderManager().playerViewX;
|
||||
GlStateManager.rotate(180.0F - Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
float r = 0.5f;
|
||||
|
||||
buffer.pos(-r, r, 0).tex(0, 0).endVertex();
|
||||
buffer.pos( r, r, 0).tex(1, 0).endVertex();
|
||||
buffer.pos( r, -r, 0).tex(1, 1).endVertex();
|
||||
buffer.pos(-r, -r, 0).tex(0, 1).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
// Reverses the colour addition change
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private void drawCube(EntityRadiantTotem entity, Tessellator tessellator, float partialTicks){
|
||||
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
float age = entity.ticksExisted + partialTicks;
|
||||
float rotationSpeed = 2;
|
||||
|
||||
GlStateManager.rotate(age * rotationSpeed/2, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(60.0F, 0.7071F, 0.0F, 0.7071F);
|
||||
GlStateManager.rotate(age * rotationSpeed, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
GlStateManager.scale(0.5, 0.5, 0.5);
|
||||
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||
|
||||
bindEntityTexture(entity);
|
||||
|
||||
Vec3d[] vertices = GeometryUtils.getVertices(entity.getEntityBoundingBox().offset(entity.getPositionVector()
|
||||
.add(0, entity.height/2, 0).scale(-1)));
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
// Outside
|
||||
drawFace(buffer, vertices[0], vertices[1], vertices[3], vertices[2], 0.5f, 0, 0.75f, 0.5f); // Bottom
|
||||
drawFace(buffer, vertices[6], vertices[7], vertices[2], vertices[3], 0.75f, 0.5f, 1, 1); // South
|
||||
drawFace(buffer, vertices[5], vertices[6], vertices[1], vertices[2], 0, 0.5f, 0.25f, 1); // East
|
||||
drawFace(buffer, vertices[4], vertices[5], vertices[0], vertices[1], 0.25f, 0.5f, 0.5f, 1); // North
|
||||
drawFace(buffer, vertices[7], vertices[4], vertices[3], vertices[0], 0.5f, 0.5f, 0.75f, 1); // West
|
||||
drawFace(buffer, vertices[5], vertices[4], vertices[6], vertices[7], 0.25f, 0, 0.5f, 0.5f); // Top
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private static void drawFace(BufferBuilder buffer, Vec3d topLeft, Vec3d topRight, Vec3d bottomLeft, Vec3d bottomRight, float u1, float v1, float u2, float v2){
|
||||
buffer.pos(topLeft.x, topLeft.y, topLeft.z).tex(u1, v1).endVertex();
|
||||
buffer.pos(topRight.x, topRight.y, topRight.z).tex(u2, v1).endVertex();
|
||||
buffer.pos(bottomRight.x, bottomRight.y, bottomRight.z).tex(u2, v2).endVertex();
|
||||
buffer.pos(bottomLeft.x, bottomLeft.y, bottomLeft.z).tex(u1, v2).endVertex();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.model.ModelRemnant;
|
||||
import electroblob.wizardry.entity.living.EntityRemnant;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RenderRemnant extends Render<EntityRemnant> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/remnant.png");
|
||||
|
||||
private final ModelRemnant model;
|
||||
|
||||
public RenderRemnant(RenderManager manager){
|
||||
super(manager);
|
||||
model = new ModelRemnant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityRemnant entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
float age = (float)entity.ticksExisted + partialTicks;
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate((float)x, (float)y, (float)z);
|
||||
this.bindTexture(TEXTURE);
|
||||
// float whatIsThis = MathHelper.sin(age * 0.2F) / 2.0F + 0.5F;
|
||||
// whatIsThis = whatIsThis * whatIsThis + whatIsThis;
|
||||
|
||||
if(this.renderOutlines){
|
||||
GlStateManager.enableColorMaterial();
|
||||
GlStateManager.enableOutlineMode(this.getTeamColor(entity));
|
||||
}
|
||||
|
||||
float expansion = 0.9f;
|
||||
|
||||
if(entity.deathTime > 0){
|
||||
float f = (entity.deathTime + partialTicks) * 0.25f;
|
||||
f = 1 - (1 / (f + 1));
|
||||
expansion -= f * 0.75f;
|
||||
|
||||
}else if(entity.hurtTime > 0){
|
||||
float f = (entity.hurtTime - partialTicks) / entity.maxHurtTime;
|
||||
// Neat bit of maths borrowed from the camera tilt effect when hurt
|
||||
f = MathHelper.sin(f * f * f * f * (float)Math.PI);
|
||||
expansion += f * 0.2f;
|
||||
}
|
||||
|
||||
// if(entity.isAttacking()) s -= 0.4f;
|
||||
float rotationSpeed = entity.isAttacking() ? 10 : 3;
|
||||
|
||||
this.model.render(entity, rotationSpeed, expansion, age, 0, 0, 0.0625f);
|
||||
|
||||
if(this.renderOutlines){
|
||||
GlStateManager.disableOutlineMode();
|
||||
GlStateManager.disableColorMaterial();
|
||||
}
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
super.doRender(entity, x, y, z, entityYaw, partialTicks);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityRemnant entity){
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
}
|
||||
+17
-17
@@ -1,6 +1,6 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.entity.construct.EntityHealAura;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.entity.construct.EntityMagicConstruct;
|
||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -18,24 +18,24 @@ import org.lwjgl.opengl.GL11;
|
||||
public class RenderSigil extends Render<EntityMagicConstruct> {
|
||||
|
||||
private final ResourceLocation texture;
|
||||
private float scale = 1.0f;
|
||||
private float rotationSpeed;
|
||||
private boolean invisibleToEnemies;
|
||||
|
||||
public RenderSigil(RenderManager renderManager, ResourceLocation texture, float scale, boolean invisibleToEnemies){
|
||||
public RenderSigil(RenderManager renderManager, ResourceLocation texture, float rotationSpeed, boolean invisibleToEnemies){
|
||||
super(renderManager);
|
||||
this.texture = texture;
|
||||
this.scale = scale;
|
||||
this.rotationSpeed = rotationSpeed;
|
||||
this.invisibleToEnemies = invisibleToEnemies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityMagicConstruct entity, double par2, double par4, double par6, float par8, float par9){
|
||||
public void doRender(EntityMagicConstruct entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
// Makes the sigil invisible to enemies of the player that created it
|
||||
if(this.invisibleToEnemies){
|
||||
// Unfortunately we can't access the caster's allies if they're not online, it only works the other way round
|
||||
if(entity.getCaster() instanceof EntityPlayer && !AllyDesignationSystem
|
||||
.isPlayerAlly((EntityPlayer)entity.getCaster(), Minecraft.getMinecraft().player)){
|
||||
if(entity.getCaster() != Minecraft.getMinecraft().player && entity.getCaster() instanceof EntityPlayer
|
||||
&& !AllyDesignationSystem.isPlayerAlly((EntityPlayer)entity.getCaster(), Minecraft.getMinecraft().player)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class RenderSigil extends Render<EntityMagicConstruct> {
|
||||
|
||||
float yOffset = 0;
|
||||
|
||||
GlStateManager.translate((float)par2, (float)par4 + yOffset, (float)par6);
|
||||
GlStateManager.translate((float)x, (float)y + yOffset, (float)z);
|
||||
|
||||
this.bindTexture(texture);
|
||||
float f6 = 1.0F;
|
||||
@@ -58,19 +58,19 @@ public class RenderSigil extends Render<EntityMagicConstruct> {
|
||||
GlStateManager.rotate(-90, 1, 0, 0);
|
||||
|
||||
// Healing aura rotates slowly
|
||||
if(entity instanceof EntityHealAura) GlStateManager.rotate(entity.ticksExisted / 3.0f, 0, 0, 1);
|
||||
if(rotationSpeed != 0) GlStateManager.rotate(entity.ticksExisted * rotationSpeed, 0, 0, 1);
|
||||
|
||||
GlStateManager.scale(scale, scale, scale);
|
||||
float s = entity.width * DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 10);
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
// tessellator.setColorRGBA_I(k1, 128);
|
||||
// buffer.normal(0.0F, 1.0F, 0.0F);
|
||||
buffer.pos((double)(0.0F - f7), (double)(0.0F - f8), 0.01).tex(0, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(0.0F - f8), 0.01).tex(1, 1).endVertex();
|
||||
buffer.pos((double)(f6 - f7), (double)(1.0F - f8), 0.01).tex(1, 0).endVertex();
|
||||
buffer.pos((double)(0.0F - f7), (double)(1.0F - f8), 0.01).tex(0, 0).endVertex();
|
||||
|
||||
buffer.pos(0.0F - f7, 0.0F - f8, 0.01).tex(0, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 0.0F - f8, 0.01).tex(1, 1).endVertex();
|
||||
buffer.pos(f6 - f7, 1.0F - f8, 0.01).tex(1, 0).endVertex();
|
||||
buffer.pos(0.0F - f7, 1.0F - f8, 0.01).tex(0, 0).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.entity.living.EntitySpiritHorse;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.entity.living.EntitySpiritWolf;
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.client.renderer.entity.layers.LayerStrayMinionClothing;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.entity.RenderSkeleton;
|
||||
import net.minecraft.entity.monster.AbstractSkeleton;
|
||||
@@ -0,0 +1,159 @@
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.entity.construct.EntityWitheringTotem;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RenderWitheringTotem extends Render<EntityWitheringTotem> {
|
||||
|
||||
private static final ResourceLocation FLARE_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/flare.png");
|
||||
private static final ResourceLocation[] CUBE_TEXTURES = new ResourceLocation[14];
|
||||
|
||||
static {
|
||||
for(int i = 0; i< CUBE_TEXTURES.length; i++) CUBE_TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/totem/cube_" + i + ".png");
|
||||
}
|
||||
|
||||
public RenderWitheringTotem(RenderManager manager){
|
||||
super(manager);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityWitheringTotem entity){
|
||||
return CUBE_TEXTURES[entity.ticksExisted % CUBE_TEXTURES.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityWitheringTotem entity, double x, double y, double z, float entityYaw, float partialTicks){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
GlStateManager.depthMask(false);
|
||||
GlStateManager.disableCull();
|
||||
|
||||
GlStateManager.translate(x, y + entity.height/2, z);
|
||||
|
||||
float charge = entity.getHealthDrained() / 50f;
|
||||
|
||||
float s = DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 10);
|
||||
s *= 1 + charge * 0.3f; // Gets bigger the more health it drains
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
drawFlare(charge, tessellator);
|
||||
drawCube(entity, tessellator, partialTicks);
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableCull();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private void drawFlare(float redness, Tessellator tessellator){
|
||||
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
int c = DrawingUtils.mix(0xb333e6, 0xff0044, redness);
|
||||
int r = c >> 16 & 255;
|
||||
int g = c >> 8 & 255;
|
||||
int b = c & 255;
|
||||
|
||||
// Makes the colour add to the colour of the texture pixels, rather than the default multiplying
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_ADD);
|
||||
GlStateManager.color(r/255f, g/255f, b/255f); // Gets redder the more health it drains
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
bindTexture(FLARE_TEXTURE);
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = Minecraft.getMinecraft().gameSettings.thirdPersonView == 2
|
||||
? Minecraft.getMinecraft().getRenderManager().playerViewX
|
||||
: -Minecraft.getMinecraft().getRenderManager().playerViewX;
|
||||
GlStateManager.rotate(180.0F - Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
float radius = 0.5f;
|
||||
|
||||
buffer.pos(-radius, radius, 0).tex(0, 0).endVertex();
|
||||
buffer.pos( radius, radius, 0).tex(1, 0).endVertex();
|
||||
buffer.pos( radius, -radius, 0).tex(1, 1).endVertex();
|
||||
buffer.pos(-radius, -radius, 0).tex(0, 1).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
// Reverses the colour addition change
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private void drawCube(EntityWitheringTotem entity, Tessellator tessellator, float partialTicks){
|
||||
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
float age = entity.ticksExisted + partialTicks;
|
||||
float rotationSpeed = 2;
|
||||
|
||||
GlStateManager.rotate(age * rotationSpeed/2, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(60.0F, 0.7071F, 0.0F, 0.7071F);
|
||||
GlStateManager.rotate(age * rotationSpeed, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
GlStateManager.scale(0.5, 0.5, 0.5);
|
||||
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||
|
||||
bindEntityTexture(entity);
|
||||
|
||||
Vec3d[] vertices = GeometryUtils.getVertices(entity.getEntityBoundingBox().offset(entity.getPositionVector()
|
||||
.add(0, entity.height/2, 0).scale(-1)));
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
// Outside
|
||||
drawFace(buffer, vertices[0], vertices[1], vertices[3], vertices[2], 0.5f, 0, 0.75f, 0.5f); // Bottom
|
||||
drawFace(buffer, vertices[6], vertices[7], vertices[2], vertices[3], 0.75f, 0.5f, 1, 1); // South
|
||||
drawFace(buffer, vertices[5], vertices[6], vertices[1], vertices[2], 0, 0.5f, 0.25f, 1); // East
|
||||
drawFace(buffer, vertices[4], vertices[5], vertices[0], vertices[1], 0.25f, 0.5f, 0.5f, 1); // North
|
||||
drawFace(buffer, vertices[7], vertices[4], vertices[3], vertices[0], 0.5f, 0.5f, 0.75f, 1); // West
|
||||
drawFace(buffer, vertices[5], vertices[4], vertices[6], vertices[7], 0.25f, 0, 0.5f, 0.5f); // Top
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
private static void drawFace(BufferBuilder buffer, Vec3d topLeft, Vec3d topRight, Vec3d bottomLeft, Vec3d bottomRight, float u1, float v1, float u2, float v2){
|
||||
buffer.pos(topLeft.x, topLeft.y, topLeft.z).tex(u1, v1).endVertex();
|
||||
buffer.pos(topRight.x, topRight.y, topRight.z).tex(u2, v1).endVertex();
|
||||
buffer.pos(bottomRight.x, bottomRight.y, bottomRight.z).tex(u2, v2).endVertex();
|
||||
buffer.pos(bottomLeft.x, bottomLeft.y, bottomLeft.z).tex(u1, v2).endVertex();
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.model.ModelWizard;
|
||||
@@ -11,14 +11,14 @@ import net.minecraft.util.ResourceLocation;
|
||||
//@SideOnly(Side.CLIENT)
|
||||
public class RenderWizard extends RenderBiped<EntityWizard> {
|
||||
|
||||
static final ResourceLocation[] textures = new ResourceLocation[6];
|
||||
static final ResourceLocation[] TEXTURES = new ResourceLocation[6];
|
||||
|
||||
public RenderWizard(RenderManager renderManager){
|
||||
|
||||
super(renderManager, new ModelWizard(), 0.5F);
|
||||
|
||||
for(int i = 0; i < 6; i++){
|
||||
textures[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/wizard_" + i + ".png");
|
||||
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/wizard/wizard_" + i + ".png");
|
||||
}
|
||||
// Just using the default without overriding models, since the armour sets its own model anyway.
|
||||
this.addLayer(new LayerBipedArmor(this));
|
||||
@@ -26,7 +26,7 @@ public class RenderWizard extends RenderBiped<EntityWizard> {
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityWizard wizard){
|
||||
return textures[wizard.textureIndex];
|
||||
return TEXTURES[wizard.textureIndex];
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.entity.living.EntityBlazeMinion;
|
||||
import net.minecraft.client.model.ModelBlaze;
|
||||
@@ -0,0 +1,115 @@
|
||||
package electroblob.wizardry.client.renderer.entity;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.entity.construct.EntityZombieSpawner;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class RenderZombieSpawner extends Render<EntityZombieSpawner> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/zombie_spawner.png");
|
||||
|
||||
private static final Vec3d[] HIDDEN_BOX = GeometryUtils.getVertices(new AxisAlignedBB(-1, 0, -1, 1, 2.5, 1));
|
||||
|
||||
public RenderZombieSpawner(RenderManager renderManager){
|
||||
super(renderManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRender(EntityZombieSpawner entity, double x, double y, double z, float yaw, float partialTicks){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GlStateManager.translate(x, y, z);
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
// The visible bit
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
float s = DrawingUtils.smoothScaleFactor(entity.lifetime, entity.ticksExisted, partialTicks, 10, 10);
|
||||
GlStateManager.scale(s, s, s);
|
||||
|
||||
GlStateManager.rotate((entity.ticksExisted + partialTicks) * 2, 0, 1, 0);
|
||||
|
||||
this.bindTexture(TEXTURE);
|
||||
|
||||
Vec3d[] vertices = GeometryUtils.getVertices(entity.getEntityBoundingBox().offset(entity.getPositionVector().scale(-1)));
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
drawFace(buffer, vertices[0], vertices[1], vertices[3], vertices[2], 0, 0, 1, 1); // Bottom
|
||||
drawFace(buffer, vertices[1], vertices[0], vertices[2], vertices[3], 0, 0, 1, 1); // Top
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
// Hidden box
|
||||
GlStateManager.disableTexture2D();
|
||||
GlStateManager.colorMask(false, false, false, false); // Magically hide the zombies
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
|
||||
|
||||
// Outside (hides everything)
|
||||
drawFaceColour(buffer, HIDDEN_BOX[6], HIDDEN_BOX[7], HIDDEN_BOX[2], HIDDEN_BOX[3], 0, 0, 0, 1); // South
|
||||
drawFaceColour(buffer, HIDDEN_BOX[5], HIDDEN_BOX[6], HIDDEN_BOX[1], HIDDEN_BOX[2], 0, 0, 0, 1); // East
|
||||
drawFaceColour(buffer, HIDDEN_BOX[4], HIDDEN_BOX[5], HIDDEN_BOX[0], HIDDEN_BOX[1], 0, 0, 0, 1); // North
|
||||
drawFaceColour(buffer, HIDDEN_BOX[7], HIDDEN_BOX[4], HIDDEN_BOX[3], HIDDEN_BOX[0], 0, 0, 0, 1); // West
|
||||
drawFaceColour(buffer, HIDDEN_BOX[5], HIDDEN_BOX[4], HIDDEN_BOX[6], HIDDEN_BOX[7], 0, 0, 0, 1); // Top
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.disableRescaleNormal();
|
||||
GlStateManager.enableTexture2D();
|
||||
GlStateManager.colorMask(true, true, true, true);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderMultipass(EntityZombieSpawner entity, double x, double y, double z, float yaw, float partialTicks){
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMultipass(){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceLocation getEntityTexture(EntityZombieSpawner entity){
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
private static void drawFace(BufferBuilder buffer, Vec3d topLeft, Vec3d topRight, Vec3d bottomLeft, Vec3d bottomRight, float u1, float v1, float u2, float v2){
|
||||
buffer.pos(topLeft.x, topLeft.y, topLeft.z).tex(u1, v1).endVertex();
|
||||
buffer.pos(topRight.x, topRight.y, topRight.z).tex(u2, v1).endVertex();
|
||||
buffer.pos(bottomRight.x, bottomRight.y, bottomRight.z).tex(u2, v2).endVertex();
|
||||
buffer.pos(bottomLeft.x, bottomLeft.y, bottomLeft.z).tex(u1, v2).endVertex();
|
||||
}
|
||||
|
||||
private static void drawFaceColour(BufferBuilder buffer, Vec3d topLeft, Vec3d topRight, Vec3d bottomLeft, Vec3d bottomRight, float r, float g, float b, float a){
|
||||
buffer.pos(topLeft.x, topLeft.y, topLeft.z).color(r, g, b, a).endVertex();
|
||||
buffer.pos(topRight.x, topRight.y, topRight.z).color(r, g, b, a).endVertex();
|
||||
buffer.pos(bottomRight.x, bottomRight.y, bottomRight.z).color(r, g, b, a).endVertex();
|
||||
buffer.pos(bottomLeft.x, bottomLeft.y, bottomLeft.z).color(r, g, b, a).endVertex();
|
||||
}
|
||||
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package electroblob.wizardry.client.renderer.entity.layers;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.spell.Disintegration;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.client.event.RenderLivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
/**
|
||||
* Layer used to render the appear/disappear animation for summoned creatures.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class LayerDisintegrateAnimation<T extends EntityLivingBase> extends LayerTiledOverlay<T> {
|
||||
|
||||
private static final int ANIMATION_TICKS = 19; // One less than the max death time
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = new ResourceLocation[ANIMATION_TICKS];
|
||||
|
||||
static {
|
||||
for(int i=0; i<ANIMATION_TICKS; i++){
|
||||
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/disintegrate_overlay/disintegrate_overlay_" + i + ".png");
|
||||
}
|
||||
}
|
||||
|
||||
public LayerDisintegrateAnimation(RenderLivingBase<?> renderer){
|
||||
super(renderer, 32, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(T entity, float partialTicks){
|
||||
return entity.getEntityData().hasKey(Disintegration.NBT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTexture(T entity, float partialTicks){
|
||||
return TEXTURES[MathHelper.clamp(entity.ticksExisted - entity.getEntityData().getInteger(Disintegration.NBT_KEY), 0, ANIMATION_TICKS - 1)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(T entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Pre<EntityLivingBase> event){
|
||||
if(event.getEntity().getEntityData().hasKey(Disintegration.NBT_KEY)){
|
||||
event.getEntity().deathTime = 0;
|
||||
event.getEntity().setInvisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Post<EntityLivingBase> event){
|
||||
if(event.getEntity().getEntityData().hasKey(Disintegration.NBT_KEY)) event.getEntity().setInvisible(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package electroblob.wizardry.client.renderer.entity.layers;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockStatue;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Layer used to render the frost texture on creatures with the frostbite effect.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 1.2
|
||||
*/
|
||||
public class LayerFrost extends LayerTiledOverlay<EntityLivingBase> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/frost_overlay.png");
|
||||
|
||||
public LayerFrost(RenderLivingBase<?> renderer){
|
||||
super(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(EntityLivingBase entity, float partialTicks){
|
||||
return !entity.isInvisible() && entity.isPotionActive(WizardryPotions.frost) || entity.getEntityData().getBoolean(BlockStatue.FROZEN_NBT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTexture(EntityLivingBase entity, float partialTicks){
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package electroblob.wizardry.client.renderer.entity.layers;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.spell.Possession;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Layer used to render the mind control overlay on creatures with the mind control effect.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
public class LayerMindControl extends LayerTiledOverlay<EntityLivingBase> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/mind_control_overlay.png");
|
||||
|
||||
public LayerMindControl(RenderLivingBase<?> renderer){
|
||||
super(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(EntityLivingBase entity, float partialTicks){
|
||||
return !entity.isInvisible() && (entity.isPotionActive(WizardryPotions.mind_control) || entity.getEntityData().getBoolean(Possession.NBT_KEY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTexture(EntityLivingBase entity, float partialTicks){
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE);
|
||||
|
||||
PotionEffect effect = entity.getActivePotionEffect(WizardryPotions.mind_control);
|
||||
if(effect != null){
|
||||
GlStateManager.color(1, 1, 1, Math.min(1, (effect.getDuration() - partialTicks) / 20));
|
||||
}
|
||||
|
||||
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyTextureSpaceTransformations(EntityLivingBase entity, float partialTicks){
|
||||
float f = entity.ticksExisted + partialTicks;
|
||||
GlStateManager.translate(f * 0.003f, f * 0.003f, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package electroblob.wizardry.client.renderer.entity.layers;
|
||||
|
||||
import electroblob.wizardry.block.BlockStatue;
|
||||
import electroblob.wizardry.client.ClientProxy;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Layer used to render the stone texture on a petrified creature.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 1.2
|
||||
*/
|
||||
// N.B. The rule here is don't restrict the type any more than necessary, so even though we *know* petrified creatures
|
||||
// are always instances of EntityLiving, we don't need any methods/fields specific to EntityLiving so use ELB instead.
|
||||
public class LayerStone extends LayerTiledOverlay<EntityLivingBase> {
|
||||
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation("textures/blocks/stone.png");
|
||||
|
||||
public LayerStone(RenderLivingBase<?> renderer){
|
||||
super(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(EntityLivingBase entity, float partialTicks){
|
||||
return entity.getEntityData().getBoolean(BlockStatue.PETRIFIED_NBT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTexture(EntityLivingBase entity, float partialTicks){
|
||||
ResourceLocation breakingTexture = ClientProxy.renderStatue.getBlockBreakingTexture();
|
||||
return breakingTexture == null ? TEXTURE : breakingTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
// N.B. It's one or the other because this effectively gets called twice via RenderStatue
|
||||
if(ClientProxy.renderStatue.getBlockBreakingTexture() != null){
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
|
||||
}else{
|
||||
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.entity.layers;
|
||||
|
||||
import electroblob.wizardry.entity.living.EntityStrayMinion;
|
||||
import net.minecraft.client.model.ModelSkeleton;
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package electroblob.wizardry.client.renderer.entity.layers;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.entity.living.ISummonedCreature;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.GlStateManager.DestFactor;
|
||||
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.RenderLivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
/**
|
||||
* Layer used to render the appear/disappear animation for summoned creatures.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class LayerSummonAnimation<T extends EntityLivingBase> extends LayerTiledOverlay<T> {
|
||||
|
||||
private static final int ANIMATION_TICKS = 19;
|
||||
private static final int HIDE_MODEL_TICKS = 9;
|
||||
|
||||
private static final ResourceLocation[] TEXTURES = new ResourceLocation[ANIMATION_TICKS];
|
||||
|
||||
static {
|
||||
for(int i=0; i<ANIMATION_TICKS; i++){
|
||||
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/summon_overlay/summon_overlay_" + i + ".png");
|
||||
}
|
||||
}
|
||||
|
||||
public LayerSummonAnimation(RenderLivingBase<?> renderer){
|
||||
super(renderer, 32, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender(T entity, float partialTicks){
|
||||
return entity instanceof ISummonedCreature && ((ISummonedCreature)entity).hasAnimation()
|
||||
&& ((ISummonedCreature)entity).getLifetime() > 0 && getFrameNumber(entity) < ANIMATION_TICKS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTexture(T entity, float partialTicks){
|
||||
return TEXTURES[getFrameNumber(entity)];
|
||||
}
|
||||
|
||||
private int getFrameNumber(T entity){
|
||||
if(!(entity instanceof ISummonedCreature)) throw new IllegalArgumentException("Entity must be an ISummonedCreature");
|
||||
return Math.min(entity.ticksExisted, Math.max(((ISummonedCreature)entity).getLifetime() - entity.ticksExisted - 1, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(T entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
if(!(entity instanceof ISummonedCreature)) return;
|
||||
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
int colour = ((ISummonedCreature)entity).getAnimationColour((float)getFrameNumber(entity) / ANIMATION_TICKS);
|
||||
GlStateManager.color((colour >> 16 & 255) / 255f, (colour >> 8 & 255) / 255f, (colour & 255) / 255f);
|
||||
|
||||
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Pre<EntityLivingBase> event){
|
||||
if(shouldHideMainModel(event.getEntity())) event.getEntity().setInvisible(true);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Post<EntityLivingBase> event){
|
||||
if(shouldHideMainModel(event.getEntity())) event.getEntity().setInvisible(false);
|
||||
}
|
||||
|
||||
private static boolean shouldHideMainModel(EntityLivingBase entity){
|
||||
return entity instanceof ISummonedCreature && ((ISummonedCreature)entity).hasAnimation()
|
||||
&& ((ISummonedCreature)entity).getLifetime() > 0 && (entity.ticksExisted < HIDE_MODEL_TICKS
|
||||
|| ((ISummonedCreature)entity).getLifetime() - entity.ticksExisted < HIDE_MODEL_TICKS);
|
||||
}
|
||||
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
package electroblob.wizardry.client.renderer.entity.layers;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelBiped;
|
||||
import net.minecraft.client.model.ModelPlayer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.entity.Render;
|
||||
import net.minecraft.client.renderer.entity.RenderLivingBase;
|
||||
import net.minecraft.client.renderer.entity.RenderPlayer;
|
||||
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Base class for layers that overlay a tiled texture onto the entity model. Handles dynamic tiling of the texture,
|
||||
* scaling to preserve in-world pixel size (1/16 of a block), and the necessary GL state changes.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
public abstract class LayerTiledOverlay<T extends EntityLivingBase> implements LayerRenderer<T> {
|
||||
|
||||
private final RenderLivingBase<?> renderer;
|
||||
|
||||
private final int textureWidth;
|
||||
private final int textureHeight;
|
||||
|
||||
/** Creates a new {@code LayerTiledOverlay} with the given renderer parameters. */
|
||||
public LayerTiledOverlay(RenderLivingBase<?> renderer, int textureWidth, int textureHeight){
|
||||
this.textureWidth = textureWidth;
|
||||
this.textureHeight = textureHeight;
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
/** Creates a new {@code LayerTiledOverlay} with the given renderer. Texture width and height default to 16. */
|
||||
public LayerTiledOverlay(RenderLivingBase<?> renderer){
|
||||
this(renderer, 16, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this layer should be rendered for the given entity, false if not.
|
||||
* @param entity The entity being rendered
|
||||
* @param partialTicks The current partial tick time
|
||||
* @return True if this layer should be rendered, false if not.
|
||||
*/
|
||||
public abstract boolean shouldRender(T entity, float partialTicks);
|
||||
|
||||
/**
|
||||
* Returns the texture to use for the overlay.
|
||||
* @param entity The entity being rendered
|
||||
* @param partialTicks The current partial tick time
|
||||
* @return A {@link ResourceLocation} specifying the texture to use.
|
||||
*/
|
||||
public abstract ResourceLocation getTexture(T entity, float partialTicks);
|
||||
|
||||
/**
|
||||
* Returns the model to use for the overlay. Defaults to the renderer's main model.
|
||||
* @param entity The entity being rendered
|
||||
* @param partialTicks The current partial tick time
|
||||
* @return The model to use. Swapping different models in dynamically is fine, but don't create new ones each time.
|
||||
*/
|
||||
public ModelBase getModel(T entity, float partialTicks){
|
||||
return renderer.getMainModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to render the second layer of mob/player skins (which is not an <i>actual</i> render layer, but
|
||||
* part of the model) as part of this layer. Defaults to false.
|
||||
* @param entity The entity being rendered
|
||||
* @param partialTicks The current partial tick time
|
||||
* @return True to render any non-hidden second layer boxes, false to always hide them from this layer.
|
||||
*/
|
||||
public boolean renderSecondLayer(T entity, float partialTicks){
|
||||
return false; // Normally it looks kind of weird because second layers typically have holes in them
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to perform additional transformations in the texture space before the model is rendered. This
|
||||
* can be used for a creeper-charge-like effect. To do this, simply override this method and call the appropriate
|
||||
* transformation method(s) (translate, rotate, scale) in {@link GlStateManager}. This method does nothing by
|
||||
* default.
|
||||
* @param entity The entity being rendered
|
||||
* @param partialTicks The current partial tick time
|
||||
*/
|
||||
protected void applyTextureSpaceTransformations(T entity, float partialTicks){}
|
||||
|
||||
@Override
|
||||
public void doRenderLayer(T entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
if(shouldRender(entity, partialTicks)){
|
||||
this.renderer.bindTexture(getTexture(entity, partialTicks));
|
||||
this.renderEntityModel(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCombineTextures(){
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static int getBlockBrightnessForEntity(Entity entity){
|
||||
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(MathHelper.floor(entity.posX), 0,
|
||||
MathHelper.floor(entity.posZ));
|
||||
|
||||
if(entity.world.isBlockLoaded(pos)){
|
||||
pos.setY(MathHelper.floor(entity.posY + (double)entity.getEyeHeight()));
|
||||
return entity.world.getCombinedLight(pos, 0);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void renderEntityModel(T entity, float limbSwing, float limbSwingAmount, float partialTicks,
|
||||
float ageInTicks, float netHeadYaw, float headPitch, float scale){
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
// Enables texture tiling (Also used for guardian beam, beacon beam and ender crystal beam, amongst others)
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
||||
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
||||
|
||||
GlStateManager.depthMask(true); // Some entities set depth mask to false (i.e. no sorting of faces by depth)
|
||||
// In particular, LayerSpiderEyes sets it to false when the spider is invisible, for some reason.
|
||||
|
||||
// Changes the scale at which the texture is applied to the model. See LayerCreeper for a similar example,
|
||||
// but with translation instead of scaling.
|
||||
// You can do all sorts of fun stuff with this, just by applying transformations in the 2D texture space.
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE); // Switch to the 2D texture space
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
ModelBase model = getModel(entity, partialTicks);
|
||||
|
||||
// Calculate the scaling required in each direction
|
||||
double scaleX = 1, scaleY = 1;
|
||||
// It's more logical to use the model's texture size, but some classes don't bother setting it properly
|
||||
// (e.g. ModelVillager), so to get the correct dimensions I'm getting them from the first box instead.
|
||||
if(model.boxList != null && model.boxList.get(0) != null){
|
||||
scaleX = (double)model.boxList.get(0).textureWidth / textureWidth;
|
||||
scaleY = (double)model.boxList.get(0).textureHeight / textureHeight;
|
||||
}else{ // Fallback to model fields; should never be needed
|
||||
scaleX = (double)model.textureWidth / textureWidth;
|
||||
scaleY = (double)model.textureHeight / textureHeight;
|
||||
}
|
||||
|
||||
GlStateManager.scale(scaleX, scaleY, 1);
|
||||
|
||||
applyTextureSpaceTransformations(entity, partialTicks);
|
||||
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW); // Switch back to the 3D model space
|
||||
|
||||
boolean headWearHidden = false;
|
||||
boolean bodyWearHidden = false;
|
||||
boolean leftArmWearHidden = false;
|
||||
boolean rightArmWearHidden = false;
|
||||
boolean leftLegWearHidden = false;
|
||||
boolean rightLegWearHidden = false;
|
||||
|
||||
if(!renderSecondLayer(entity, partialTicks)){
|
||||
// Hide the hat layer for bipeds, and all the other body part overlays for players
|
||||
if(model instanceof ModelBiped){
|
||||
headWearHidden = ((ModelBiped)model).bipedHeadwear.isHidden;
|
||||
((ModelBiped)model).bipedHeadwear.isHidden = true;
|
||||
}
|
||||
|
||||
if(model instanceof ModelPlayer){
|
||||
bodyWearHidden = ((ModelPlayer)model).bipedBodyWear.isHidden;
|
||||
leftArmWearHidden = ((ModelPlayer)model).bipedLeftArmwear.isHidden;
|
||||
rightArmWearHidden = ((ModelPlayer)model).bipedRightArmwear.isHidden;
|
||||
leftLegWearHidden = ((ModelPlayer)model).bipedLeftLegwear.isHidden;
|
||||
rightLegWearHidden = ((ModelPlayer)model).bipedRightLegwear.isHidden;
|
||||
((ModelPlayer)model).bipedBodyWear.isHidden = true;
|
||||
((ModelPlayer)model).bipedLeftArmwear.isHidden = true;
|
||||
((ModelPlayer)model).bipedRightArmwear.isHidden = true;
|
||||
((ModelPlayer)model).bipedLeftLegwear.isHidden = true;
|
||||
((ModelPlayer)model).bipedRightLegwear.isHidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Actually render the model
|
||||
model.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks);
|
||||
model.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
|
||||
|
||||
if(!renderSecondLayer(entity, partialTicks)){
|
||||
// Reset the hidden status of everything to how it was before
|
||||
if(model instanceof ModelBiped){
|
||||
((ModelBiped)model).bipedHeadwear.isHidden = headWearHidden;
|
||||
}
|
||||
|
||||
if(model instanceof ModelPlayer){
|
||||
((ModelPlayer)model).bipedBodyWear.isHidden = bodyWearHidden;
|
||||
((ModelPlayer)model).bipedLeftArmwear.isHidden = leftArmWearHidden;
|
||||
((ModelPlayer)model).bipedRightArmwear.isHidden = rightArmWearHidden;
|
||||
((ModelPlayer)model).bipedLeftLegwear.isHidden = leftLegWearHidden;
|
||||
((ModelPlayer)model).bipedRightLegwear.isHidden = rightLegWearHidden;
|
||||
}
|
||||
}
|
||||
|
||||
// Undo the texture scaling
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
GlStateManager.loadIdentity();
|
||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to initialise a layer renderer for all applicable renderers. This method will work for any layer
|
||||
* renderer, not just instances of {@code LayerTiledOverlay} (it is stored here purely for convenience).
|
||||
* @param entityType The class of entity to initialise this layer renderer for (including subclasses)
|
||||
* @param layerFactory A function that creates a layer for a given renderer, usually a constructor reference
|
||||
* @param <T> The type of entity this layer renderer is applicable for
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends EntityLivingBase> void initialiseLayers(Class<T> entityType, Function<RenderLivingBase<T>, LayerRenderer<? extends T>> layerFactory){
|
||||
|
||||
for(Class<? extends Entity> c : Minecraft.getMinecraft().getRenderManager().entityRenderMap.keySet()){
|
||||
if(entityType.isAssignableFrom(c)){
|
||||
Render<T> renderer = Minecraft.getMinecraft().getRenderManager().getEntityClassRenderObject(c);
|
||||
if(renderer instanceof RenderLivingBase<?>){ // Should always be true
|
||||
// For some reason IntelliJ is quite happy with this cast, even without suppress warnings
|
||||
// Instinct suggests Java shouldn't be happy casting to RenderLivingBase<T> but somehow it works
|
||||
((RenderLivingBase<T>)renderer).addLayer(layerFactory.apply((RenderLivingBase<T>)renderer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Players have a separate renderer map
|
||||
if(entityType.isAssignableFrom(EntityPlayer.class)){
|
||||
for(RenderPlayer renderer : Minecraft.getMinecraft().getRenderManager().getSkinMap().values()){
|
||||
renderer.addLayer(layerFactory.apply((RenderLivingBase<T>)renderer)); // This does need suppress warnings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to initialise a layer renderer for all living entity renderers. This is a shorthand version of
|
||||
* {@link LayerTiledOverlay#initialiseLayers(Class, Function)}.
|
||||
* @param layerFactory A function that creates a layer for a given renderer, usually a constructor reference
|
||||
*/
|
||||
public static void initialiseLayers(Function<RenderLivingBase<EntityLivingBase>, LayerRenderer<? extends EntityLivingBase>> layerFactory){
|
||||
initialiseLayers(EntityLivingBase.class, layerFactory);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package electroblob.wizardry.client.renderer.overlay;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.WizardryClientEventHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.FOVUpdateEvent;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderBlinkEffect {
|
||||
|
||||
/** The remaining time for which the blink screen overlay effect will be displayed in first-person. Since this is
|
||||
* only for the first-person player (the instance of which is itself stored in a static variable), this can simply
|
||||
* be stored statically here, rather than needing to be in {@code WizardData}. */
|
||||
private static int blinkEffectTimer;
|
||||
/** The number of ticks the blink effect lasts for. */
|
||||
private static final int BLINK_EFFECT_DURATION = 8;
|
||||
|
||||
private static final ResourceLocation SCREEN_OVERLAY_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/blink_overlay.png");
|
||||
|
||||
/** Starts the first-person blink overlay effect. */
|
||||
public static void playBlinkEffect(){
|
||||
if(Wizardry.settings.blinkEffect) blinkEffectTimer = BLINK_EFFECT_DURATION;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event){
|
||||
|
||||
if(event.player == Minecraft.getMinecraft().player && event.phase == TickEvent.Phase.END){
|
||||
|
||||
if(Wizardry.settings.blinkEffect){
|
||||
if(blinkEffectTimer > 0) blinkEffectTimer--;
|
||||
}else{
|
||||
blinkEffectTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onFOVUpdateEvent(FOVUpdateEvent event){
|
||||
|
||||
if(blinkEffectTimer > 0){
|
||||
float f = ((float)Math.max(blinkEffectTimer - 2, 0))/BLINK_EFFECT_DURATION;
|
||||
event.setNewfov(event.getFov() + f * f * 0.7f);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGameOverlayEvent(RenderGameOverlayEvent.Post event){
|
||||
|
||||
if(event.getType() == RenderGameOverlayEvent.ElementType.HELMET){
|
||||
|
||||
if(blinkEffectTimer > 0){
|
||||
|
||||
float alpha = ((float)blinkEffectTimer)/BLINK_EFFECT_DURATION;
|
||||
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GlStateManager.color(1, 1, 1, alpha);
|
||||
GlStateManager.disableAlpha();
|
||||
|
||||
WizardryClientEventHandler.renderScreenOverlay(event.getResolution(), SCREEN_OVERLAY_TEXTURE);
|
||||
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package electroblob.wizardry.client.renderer.overlay;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.WizardryClientEventHandler;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderFrostOverlay {
|
||||
|
||||
private static final ResourceLocation SCREEN_OVERLAY_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/frost_overlay.png");
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGameOverlayEvent(RenderGameOverlayEvent.Post event){
|
||||
|
||||
if(event.getType() == RenderGameOverlayEvent.ElementType.HELMET){
|
||||
|
||||
if(Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.frost)){
|
||||
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
GlStateManager.disableAlpha();
|
||||
|
||||
WizardryClientEventHandler.renderScreenOverlay(event.getResolution(), SCREEN_OVERLAY_TEXTURE);
|
||||
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package electroblob.wizardry.client.renderer.overlay;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.WizardryClientEventHandler;
|
||||
import electroblob.wizardry.constants.Constants;
|
||||
import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.item.EntityArmorStand;
|
||||
import net.minecraft.entity.monster.IMob;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.client.event.RenderLivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderSixthSense {
|
||||
|
||||
private static final ResourceLocation MARKER_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/sixth_sense_marker.png");
|
||||
private static final ResourceLocation SCREEN_OVERLAY_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/sixth_sense_overlay.png");
|
||||
|
||||
private static final int PASSIVE_MOB_MARKER_COLOUR = 0xc6ff00;
|
||||
private static final int HOSTILE_MOB_MARKER_COLOUR = 0x004a97;
|
||||
private static final int PLAYER_MARKER_COLOUR = 0xffffff;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderGameOverlayEvent(RenderGameOverlayEvent.Post event){
|
||||
|
||||
if(event.getType() == RenderGameOverlayEvent.ElementType.HELMET){
|
||||
|
||||
if(Minecraft.getMinecraft().player.isPotionActive(WizardryPotions.sixth_sense)){
|
||||
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
GlStateManager.disableAlpha();
|
||||
|
||||
WizardryClientEventHandler.renderScreenOverlay(event.getResolution(), SCREEN_OVERLAY_TEXTURE);
|
||||
|
||||
GlStateManager.enableAlpha();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Post<EntityLivingBase> event){
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
RenderManager renderManager = event.getRenderer().getRenderManager();
|
||||
|
||||
if(mc.player.isPotionActive(WizardryPotions.sixth_sense) && !(event.getEntity() instanceof EntityArmorStand)
|
||||
&& event.getEntity() != mc.player && mc.player.getActivePotionEffect(WizardryPotions.sixth_sense) != null
|
||||
&& event.getEntity().getDistance(mc.player) < Spells.sixth_sense.getProperty(Spell.EFFECT_RADIUS).floatValue()
|
||||
* (1 + mc.player.getActivePotionEffect(WizardryPotions.sixth_sense).getAmplifier() * Constants.RANGE_INCREASE_PER_LEVEL)){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
// Disabling depth test allows it to be seen through everything.
|
||||
GlStateManager.disableDepth();
|
||||
|
||||
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height * 0.6, event.getZ());
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = mc.gameSettings.thirdPersonView == 2 ? renderManager.playerViewX : -renderManager.playerViewX;
|
||||
GlStateManager.rotate(180 - renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
// Makes the colour add to the colour of the texture pixels, rather than the default multiplying
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_ADD);
|
||||
|
||||
int colour = PASSIVE_MOB_MARKER_COLOUR;
|
||||
|
||||
if(ItemArtefact.isArtefactActive(mc.player, WizardryItems.charm_sixth_sense)){
|
||||
if(event.getEntity() instanceof IMob) colour = HOSTILE_MOB_MARKER_COLOUR;
|
||||
else if(event.getEntity() instanceof EntityPlayer) colour = PLAYER_MARKER_COLOUR;
|
||||
}
|
||||
|
||||
int r = colour >> 16 & 255;
|
||||
int g = colour >> 8 & 255;
|
||||
int b = colour & 255;
|
||||
|
||||
GlStateManager.color(r/255f, g/255f, b/255f, 1);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
mc.renderEngine.bindTexture(MARKER_TEXTURE);
|
||||
|
||||
buffer.pos(-0.6, 0.6, 0).tex(0, 0).endVertex();
|
||||
buffer.pos(0.6, 0.6, 0).tex(1, 0).endVertex();
|
||||
buffer.pos(0.6, -0.6, 0).tex(1, 1).endVertex();
|
||||
buffer.pos(-0.6, -0.6, 0).tex(0, 1).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableCull();
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.enableDepth();
|
||||
// Reverses the colour addition change from before
|
||||
GlStateManager.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package electroblob.wizardry.client.renderer.overlay;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.item.ISpellCastingItem;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import electroblob.wizardry.util.RayTracer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraftforge.client.event.RenderLivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@EventBusSubscriber(Side.CLIENT)
|
||||
public class RenderTargetPointers {
|
||||
|
||||
private static final ResourceLocation POINTER_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/pointer.png");
|
||||
private static final ResourceLocation TARGET_POINTER_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/target_pointer.png");
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderLivingEvent(RenderLivingEvent.Post<EntityLivingBase> event){
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
WizardData data = WizardData.get(mc.player);
|
||||
RenderManager renderManager = event.getRenderer().getRenderManager();
|
||||
|
||||
ItemStack wand = mc.player.getHeldItemMainhand();
|
||||
|
||||
if(!(wand.getItem() instanceof ISpellCastingItem)){
|
||||
wand = mc.player.getHeldItemOffhand();
|
||||
}
|
||||
|
||||
// Target selection pointer
|
||||
if(mc.player.isSneaking() && wand.getItem() instanceof ISpellCastingItem && EntityUtils.isLiving(event.getEntity())
|
||||
&& data != null && data.selectedMinion != null){
|
||||
|
||||
// -> Moved this in here so it isn't called every tick
|
||||
RayTraceResult rayTrace = RayTracer.standardEntityRayTrace(mc.world, mc.player, 16, false);
|
||||
|
||||
if(rayTrace != null && rayTrace.entityHit == event.getEntity()){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
// Disabling depth test allows it to be seen through everything.
|
||||
GlStateManager.disableDepth();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
|
||||
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height + 0.5, event.getZ());
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = mc.gameSettings.thirdPersonView == 2 ? renderManager.playerViewX : -renderManager.playerViewX;
|
||||
GlStateManager.rotate(180 - renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
mc.renderEngine.bindTexture(TARGET_POINTER_TEXTURE);
|
||||
|
||||
buffer.pos(-0.2, 0.24, 0).tex(0, 0).endVertex();
|
||||
buffer.pos(0.2, 0.24, 0).tex(9f / 16f, 0).endVertex();
|
||||
buffer.pos(0.2, -0.24, 0).tex(9f / 16f, 11f / 16f).endVertex();
|
||||
buffer.pos(-0.2, -0.24, 0).tex(0, 11f / 16f).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableCull();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.enableDepth();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
// Summoned creature selection pointer
|
||||
if(data != null && data.selectedMinion != null && data.selectedMinion.get() == event.getEntity()){
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
|
||||
GlStateManager.disableCull();
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
|
||||
// Disabling depth test allows it to be seen through everything.
|
||||
GlStateManager.disableDepth();
|
||||
GlStateManager.color(1, 1, 1, 1);
|
||||
|
||||
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height + 0.5, event.getZ());
|
||||
|
||||
// This counteracts the reverse rotation behaviour when in front f5 view.
|
||||
// Fun fact: this is a bug with vanilla too! Look at a snowball in front f5 view, for example.
|
||||
float yaw = mc.gameSettings.thirdPersonView == 2 ? renderManager.playerViewX : -renderManager.playerViewX;
|
||||
GlStateManager.rotate(180 - renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
|
||||
GlStateManager.rotate(yaw, 1.0F, 0.0F, 0.0F);
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
|
||||
|
||||
mc.renderEngine.bindTexture(POINTER_TEXTURE);
|
||||
|
||||
buffer.pos(-0.2, 0.24, 0).tex(0, 0).endVertex();
|
||||
buffer.pos(0.2, 0.24, 0).tex(9f / 16f, 0).endVertex();
|
||||
buffer.pos(0.2, -0.24, 0).tex(9f / 16f, 11f / 16f).endVertex();
|
||||
buffer.pos(-0.2, -0.24, 0).tex(0, 11f / 16f).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableCull();
|
||||
GlStateManager.enableLighting();
|
||||
GlStateManager.enableDepth();
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+11
-11
@@ -1,4 +1,4 @@
|
||||
package electroblob.wizardry.client.renderer;
|
||||
package electroblob.wizardry.client.renderer.overlay;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
@@ -7,8 +7,8 @@ import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.spell.Transportation;
|
||||
import electroblob.wizardry.util.GeometryUtils;
|
||||
import electroblob.wizardry.util.Location;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
@@ -84,13 +84,13 @@ public class RenderTransportationUI {
|
||||
|
||||
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
|
||||
|
||||
Vec3d position = WizardryUtilities.getCentre(location.pos).subtract(origin);
|
||||
Vec3d position = GeometryUtils.getCentre(location.pos).subtract(origin);
|
||||
double distance = position.length();
|
||||
// The icon lines up perfectly if you render it at actual distance, otherwise view bobbing messes things up
|
||||
// However, if that's outside the render distance it won't render at all! To fudge our way around this
|
||||
// problem, we're capping the distance to just below the render distance and adjusting the scale accordingly
|
||||
double distanceCap = Minecraft.getMinecraft().gameSettings.renderDistanceChunks * 16 - 8;
|
||||
double displayDist = distance > distanceCap ? distanceCap : distance;
|
||||
double displayDist = Math.min(distance, distanceCap);
|
||||
double factor = displayDist/distance;
|
||||
|
||||
GlStateManager.translate(position.x * factor, position.y * factor, position.z * factor);
|
||||
@@ -109,9 +109,9 @@ public class RenderTransportationUI {
|
||||
|
||||
float f = location == target ? 1 : 0.5f; // Makes it obvious which one is being aimed at
|
||||
|
||||
buffer.pos(-iconSize, iconSize, 0).tex(0, 0).color(f, 1, f, f).endVertex();
|
||||
buffer.pos(iconSize, iconSize, 0).tex(1, 0).color(f, 1, f, f).endVertex();
|
||||
buffer.pos(iconSize, -iconSize, 0).tex(1, 1).color(f, 1, f, f).endVertex();
|
||||
buffer.pos(-iconSize, iconSize, 0).tex(0, 0).color(f, 1, f, f).endVertex();
|
||||
buffer.pos( iconSize, iconSize, 0).tex(1, 0).color(f, 1, f, f).endVertex();
|
||||
buffer.pos( iconSize, -iconSize, 0).tex(1, 1).color(f, 1, f, f).endVertex();
|
||||
buffer.pos(-iconSize, -iconSize, 0).tex(0, 1).color(f, 1, f, f).endVertex();
|
||||
|
||||
tessellator.draw();
|
||||
@@ -157,10 +157,10 @@ public class RenderTransportationUI {
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder bufferbuilder = tessellator.getBuffer();
|
||||
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR);
|
||||
bufferbuilder.pos((double)(-i - 1), (double)(-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
bufferbuilder.pos((double)(-i - 1), (double)(8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
bufferbuilder.pos((double)(i + 1), (double)(8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
bufferbuilder.pos((double)(i + 1), (double)(-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
bufferbuilder.pos((-i - 1), (-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
bufferbuilder.pos((-i - 1), ( 8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
bufferbuilder.pos(( i + 1), ( 8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
bufferbuilder.pos(( i + 1), (-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
|
||||
tessellator.draw();
|
||||
GlStateManager.enableTexture2D();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user