Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

  • Author

In the Render class

Spoiler

package com.ninja3659.explorationexpansion.client.renders;

import com.ninja3659.explorationexpansion.client.entities.EntityBeelzebook;
import com.ninja3659.explorationexpansion.client.model.ModelBeelzebook;

import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.ResourceLocation;

public class RenderBeelzebook extends RenderLiving<EntityBeelzebook>{

	private static final ResourceLocation TEXTURES = new ResourceLocation("neem:textures/entity/beelzebook/beelzebook.png");
	
	public RenderBeelzebook(RenderManager manager) {
		super(manager, new ModelBeelzebook(), 3);
	}
	
	@Override
	protected ResourceLocation getEntityTexture(EntityBeelzebook entity) {
		return TEXTURES;
	}

}

 

And then in ClientProxy:

Spoiler

@Override
	public void registerRenders() {
		ModItems.registerRenders();
		ModTools.registerRenders();
		ModBlocks.registerRenders();
		RenderingRegistry.registerEntityRenderingHandler(EntityChimera.class, new IRenderFactory<EntityChimera>() {

			@Override
			public Render<? super EntityChimera> createRenderFor(RenderManager manager) {
				return new RenderChimera(manager);
			}
		
		});
		RenderingRegistry.registerEntityRenderingHandler(EntityMindFlayer.class, new IRenderFactory<EntityMindFlayer>() {
			
			@Override
			public Render<? super EntityMindFlayer> createRenderFor(RenderManager manager) {
				return new RenderFlayer(manager);
			}
		});
		RenderingRegistry.registerEntityRenderingHandler(EntityBeelzebook.class, new IRenderFactory<EntityBeelzebook>() {

			@Override
			public Render<? super EntityBeelzebook> createRenderFor(RenderManager manager) {
				// TODO Auto-generated method stub
				return new RenderBeelzebook(manager);
			}
			
		});
		Utils.getLogger().info("Rendered Chimera");
	}

 

 

Edited by GooberGunter

Your render class returns a new instance of ModelBeelzebook, but your packet updates the model which you have stored in a field in the entity and which does nothing. Instead you should make the model render depending on the entity's awake status, and use the packet to update the entity itself.

  • Author

So, like, have a getModel method in the entity class and then in render call said method and have the packet store the entity not the boolean?

 

If so, then how would I go about that writing the entity to bytes? And wouldn't the entity be a lot to write back and forth?

Edited by GooberGunter

user action -> entity on server gets awake -> send packet -> packet handler sets the same value on the client entity -> renderer reads the data in the entity when rendering the model

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

It's run on both. But most behaviour is controlled from the server, so if the client needs to know something you have to send it.

And specifically, the LivingHurtEvent only runs server-side.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

  • Author

Ok so since I had the server-sided LivingHurtEvent change a boolean, it only changed it on the server side, so I need to update the entire entity on the clientside through packets, right?

Just now, GooberGunter said:

Ok so since I had the server-sided LivingHurtEvent change a boolean, it only changed it on the server side, so I need to update the entire entity on the clientside through packets, right?

That's it!

9 minutes ago, GooberGunter said:

I never thought I'd get it. So...one last question. How do I set up a packet to handle an entity since it's not a basic field

You've already got a packet that handles an entity - it finds the correct one using its id. You just need to set the boolean in the entity itself, rather than setting in the entity's model field (which is unused and pointless anyway).

  • Author

Alright it works! Kinda. When I trigger the event, it updates all the entities of the same type

Here is the updated packet 

Spoiler

void proccessMessage(PacketReturnAwaken message, MessageContext ctx) {
			try {
				EntityBeelzebook eb = (EntityBeelzebook) Minecraft.getMinecraft().world.getEntityByID(message.entityid);
				eb.setEntityAwake(message.awake);
				Utils.getLogger().info("packet set: " + eb.getentityAwake());
			}catch(Exception e) {
				Utils.getLogger().catching(e);
			}
		}

 

 

Is your model checking the entity's boolean field when it needs to know the awake status? Can you show where you do this?

  • Author

Yeah here:

Spoiler

public void AwakeAnimation(EntityBeelzebook entity) {
		if(entity.getentityAwake()) {
			this.setRotation(Eye1, 33, 0, 0);
			this.setRotation(Eye2, 33, 0, 0);
			Utils.getLogger().info("animation!");
		}
	}//opens the book's eyes

 

 I should also note that right now, in the render class, it is still marked as new ModelBeelzebook();

Edited by GooberGunter

7 hours ago, GooberGunter said:

Also. Side-note: how to I isolate every change to the model class per entity?

Could you post your whole Render class. 

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

  • Author

Render class:

Spoiler

package com.ninja3659.explorationexpansion.client.renders;

import com.ninja3659.explorationexpansion.client.entities.EntityBeelzebook;
import com.ninja3659.explorationexpansion.client.model.ModelBeelzebook;

import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.ResourceLocation;

public class RenderBeelzebook extends RenderLiving<EntityBeelzebook>{

	private static final ResourceLocation TEXTURES = new ResourceLocation("neem:textures/entity/beelzebook/beelzebook.png");
	
	public RenderBeelzebook(RenderManager manager) {
		super(manager, new EntityBeelzebook(Minecraft.getMinecraft().world).getModel(), 3);
	}
	
	@Override
	protected ResourceLocation getEntityTexture(EntityBeelzebook entity) {
		return TEXTURES;
	}

}

 

 

4 minutes ago, GooberGunter said:

Render class:

  Reveal hidden contents


package com.ninja3659.explorationexpansion.client.renders;

import com.ninja3659.explorationexpansion.client.entities.EntityBeelzebook;
import com.ninja3659.explorationexpansion.client.model.ModelBeelzebook;

import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.ResourceLocation;

public class RenderBeelzebook extends RenderLiving<EntityBeelzebook>{

	private static final ResourceLocation TEXTURES = new ResourceLocation("neem:textures/entity/beelzebook/beelzebook.png");
	
	public RenderBeelzebook(RenderManager manager) {
		super(manager, new EntityBeelzebook(Minecraft.getMinecraft().world).getModel(), 3);
	}
	
	@Override
	protected ResourceLocation getEntityTexture(EntityBeelzebook entity) {
		return TEXTURES;
	}

}

 

 

In your constructor the second pararmeter of the super needs to be a new Model.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Migrate the awake field to your entity class from your model then. Most likely your model is a singleton(and it should be) so a change to this field will change the model of all your entities.

EDIT: haven't noticed all other classes you've posted with those changes. Could you please post your entity class?

Edited by V0idWa1k3r

  • Author

Here's the entity class

Spoiler

package com.ninja3659.explorationexpansion.client.entities;

import com.ninja3659.explorationexpansion.client.ai.EntityAIWander3d;
import com.ninja3659.explorationexpansion.client.model.ModelBeelzebook;
import com.ninja3659.explorationexpansion.networking.NeemPacketHandler;
import com.ninja3659.explorationexpansion.networking.PacketReturnAwaken;
import com.ninja3659.explorationexpansion.util.Utils;

import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityFlying;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIFindEntityNearestPlayer;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.monster.EntityGhast;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class EntityBeelzebook extends EntityFlying implements IMob {

	ModelBeelzebook bookmodel = new ModelBeelzebook();
	public boolean entityAwake;
	public int sync;
	
	public EntityBeelzebook(World worldIn) {
		super(worldIn);
		this.experienceValue = 200;
		this.setSize(2, .5f);
		this.moveHelper = new BeelzebookMoveHelper(this);
		moveHelper.setMoveTo(0, 10, 0, 1D);
		this.entityAwake = false;
		sync = 0;
		
	}
	
	
	@Override
	protected void entityInit() {
		super.entityInit();
	}
	
	
	@Override
	public void onUpdate() {
		super.onUpdate();
		if(entityAwake) {
			//Utils.getLogger().info("AWAKENED");
		}
	}
	
	@Override
	protected void initEntityAI() {
		if(entityAwake) {
			applyAttackAI();
			Utils.getLogger().info("AI updated");
		}
	}
	
	public boolean getentityAwake() {
		return entityAwake;
	}
	
	public void setEntityAwake(boolean truth) {
		this.entityAwake = truth;
	}
	
	public ModelBeelzebook getModel() {
		return this.bookmodel;
	}
	
	
	protected void applyAttackAI() {
		this.tasks.addTask(0, new EntityAIDeath(this, deathTime));
		this.targetTasks.addTask(1, new EntityAIWatchClosest(this, EntityPlayer.class, 32));
		this.targetTasks.addTask(0, new EntityAIFindEntityNearestPlayer(this));
		this.tasks.addTask(0, new EntityAIWander3d(this, 1.0D, 1));
		//Utils.getLogger().info("now we work");
	}
	
	@Override
	protected void onDeathUpdate() {

        ++this.deathTime;
        
        if (this.deathTime != 0) {
        }
        
        if (this.deathTime == 200)
        {
            if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean("doMobLoot")))
            {
                int i = this.getExperiencePoints(this.attackingPlayer);
                i = net.minecraftforge.event.ForgeEventFactory.getExperienceDrop(this, this.attackingPlayer, i);
                while (i > 0)
                {
                    int j = EntityXPOrb.getXPSplit(i);
                    i -= j;
                    this.world.spawnEntity(new EntityXPOrb(this.world, this.posX, this.posY, this.posZ, j));
                }
            }
            
            this.setDead();

            for (int k = 0; k < 20; ++k)
            {
                double d2 = this.rand.nextGaussian() * 0.02D;
                double d0 = this.rand.nextGaussian() * 0.02D;
                double d1 = this.rand.nextGaussian() * 0.02D;
                this.world.spawnParticle(EnumParticleTypes.EXPLOSION_NORMAL, this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, d2, d0, d1, new int[0]);
            }
        }		
	}
	
	
	public int getdeathTime() {
		return this.deathTime;
	}
	
	
	
	@Override
	public void onLivingUpdate() {
		super.onLivingUpdate();
		if(entityAwake) {
			applyAttackAI();
		}
		sync++;
		sync %= 20;
		if(sync == 0 && entityAwake) {
			NeemPacketHandler.INSTANCE.sendToAll(new PacketReturnAwaken(this.getentityAwake(), this.getEntityId()));
			Utils.getLogger().info("synched!: " + entityAwake);
		}
	}
	
	public double getPosX() {
		return this.posX;
	}
	
	public double getPosY() {
		return this.posY;
	}
	
	public double getPosZ() {
		return this.posZ;
	}
	
	public EntityBeelzebook getEntity() {
		return this;
	}
	
	static class BeelzebookMoveHelper extends EntityMoveHelper {
		private final EntityBeelzebook parentEntity;
		private int courseCooldown;
		
		public BeelzebookMoveHelper(EntityBeelzebook book) {
			super(book);
			this.parentEntity = book;
		}
		
		public void onUpdateMoveHelper() {
			if (this.action == EntityMoveHelper.Action.MOVE_TO) {
				double dx = this.posX - this.parentEntity.posX;
				double dy = this.posY - this.parentEntity.posY;
				double dz = this.posZ - this.parentEntity.posZ;
				double df = dx * dx + dy * dy + dz * dz;
				
				if(this.courseCooldown-- <=0) {
					this.courseCooldown += this.parentEntity.getRNG().nextInt(5) + 2;
					df = (double)MathHelper.sqrt(df);
					
					if(this.isNotColliding(this.posX, this.posY, this.posZ, df)) {
						this.parentEntity.motionX += dx/df * .1D;
						this.parentEntity.motionY += dy/df * .1D;
						this.parentEntity.motionZ += dz/df * .1D;
					}
					else {
						this.action = EntityMoveHelper.Action.WAIT;
					}
				}
			}
		}
		
		private boolean isNotColliding(double x, double y, double z, double dividend) {
			double d0 = (x - this.parentEntity.posX) / dividend;
			double d1 = (y - this.parentEntity.posY) / dividend;
			double d2 = (z - this.parentEntity.posZ) / dividend;
			AxisAlignedBB ax = this.parentEntity.getEntityBoundingBox();
		
			for (int i =1; (double)i < dividend; ++i) {
				ax = ax.offset(d0, d1, d2);
				
				if(!this.parentEntity.world.getCollisionBoxes(this.parentEntity, ax).isEmpty()) {
					return false;
				}
			}
			
			return true;
		}
	}
}

class EntityAIDeath extends EntityAIBase{

	protected int death;
	protected EntityBeelzebook book;
	
	public EntityAIDeath(EntityBeelzebook entity, int deathT) {
		this.death = deathT;
		this.book = entity;
		setMutexBits(8);
	}
	
	@Override
	public boolean shouldExecute() {
		if (death != 0) {
			return true;
		}
		else {
			return false;
		}
	}
	
	@Override
	public boolean continueExecuting() {
		// TODO Auto-generated method stub
		return false;
	}
	
	@Override
	public void startExecuting() {
		this.book.getMoveHelper().setMoveTo(book.posX, book.posY + 10, book.posZ, 1D);
	}
	
}

 

 

Don't create a new instance of your model in your entity class, models should be singletons. Models are also client-side only.

If your model class haven't changed since you've last posted it then the problem lies in the fact that you need to handle both cases on your AwakeAnimation method - if the entity is awake, and if they are not. Currently you are changing the rotation angles on the model if the entity is awake... which changes them for all entities as models are singletons. 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.