Jump to content

Client-Side Event Needs to be Ran Server-Side


Jimmeh

Recommended Posts

Hey there!

 

So I'm making an "ability" where a player left clicks in the air with an empty hand, and a floating rock spawns and follows the player around. It's suppose to emulate earth bending from Avatar the Last Airbender. I have the PlayerInteractEvent.LeftClickEmpty set up correctly and the entity is spawning correctly, so that's all good. However, this is only being ran client side, meaning that when the EntityRock extends EntityTameable spawns, the super constructor for EntityLiving isn't running the "initEntityAI" code. I suppose I could just call it myself, but I'm willing to bet it's been written that way for a particular reason, perhaps meaning "logic" should be done server-side?

 

Any thoughts or help are appreciated! :D

 

Here's the event:

@SubscribeEvent
    public void onLeftClick(PlayerInteractEvent.LeftClickEmpty event){

        System.out.println("SIDE: " + event.getSide().toString());
        EntityPlayer player = event.getEntityPlayer();

        if(player.getHeldItem(EnumHand.MAIN_HAND) == null && player.equals(ClientProxy.MINECRAFT.thePlayer)){
            EntityRock entity;

            entity = new EntityRock(player.worldObj);

            entity.setLocationAndAngles(player.posX, player.posY, player.posZ, MathHelper.wrapDegrees(player.worldObj.rand.nextFloat() * 360.0F), 0.0F);
            entity.rotationYawHead = entity.rotationYaw;
            entity.renderYawOffset = entity.rotationYaw;
            entity.onInitialSpawn(player.worldObj.getDifficultyForLocation(new BlockPos(entity)), (IEntityLivingData)null);
            player.worldObj.spawnEntityInWorld(entity);
            entity.playLivingSound();

            ClientProxy.clientInfo.rocks.add(entity);
        }
    }

 

Here's the EntityRock class:

public class EntityRock extends EntityTameable {

    //Some code copied from Blaze class

    private EntityLivingBase owner;
    private double maxTravelDistance;
    private BlockPos startPosition;
    private double randomGeneratedOffset;
    private float heightOffset;
    /** ticks until heightOffset is randomized */
    private int heightOffsetUpdateTime;
    private EntityAIFollowOwner followTask;
    private EntityAITargetBlock launhTask;
    private EntityAITargetEntity entityLaunchTask;

    public EntityRock(World worldIn) {
        super(worldIn);

        this.owner = ClientProxy.MINECRAFT.thePlayer;
        this.setSize(1f, 1f);
        this.experienceValue = 200;
        this.stepHeight = 1;
        randomGeneratedOffset = this.rand.nextInt(3); //0 - 2
        //this.navigator = getNewNavigator(this.worldObj);
        this.setOwnerId(owner.getUniqueID());
        this.posX = owner.posX + this.rand.nextInt(3);
        this.posY = owner.getEyeHeight() + 1;
        this.posZ = owner.posZ + this.rand.nextInt(3);
        this.setHomePosAndDistance(new BlockPos(posX, posY, posZ), Integer.MAX_VALUE);
    }

    @Override
    protected void initEntityAI(){
        System.out.println("AI INIT");
        //this.tasks.addTask(0, new EntityAIFollowBender(this, ClientProxy.MINECRAFT.thePlayer, 1f, 1.5f, 2.0f));
        this.tasks.addTask(0, followTask = new EntityAIFollowOwner(this, 0.5D, 1.5f, 2f));
    }

    @Override
    protected void applyEntityAttributes(){
        super.applyEntityAttributes();

        this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(200.0D); //100 full hearts
        this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(1.0D);
    }

    public void launch(EntityPlayer player) {
        int yaw = (int)player.rotationYaw;

        if(yaw<0) {            //due to the yaw running a -360 to positive 360
            yaw += 360;
        }        //not sure why it's that way
        yaw+=22;     //centers coordinates you may want to drop this line
        yaw%=360;  //and this one if you want a strict interpretation of the zones

        int facing = yaw/45;   //  360degrees divided by 45 == 8 zones (4 normal direction, 4 diagonal)

        //-----------------------
        RayTraceResult result = player.worldObj.rayTraceBlocks(player.getPositionEyes(1.0f), player.getLookVec());
        //remove task of following owner
        //add task of going to target
        //turn step height to 0
        //mark start position
        //play sound

        if(result == null)
            return;

        if(result.typeOfHit != RayTraceResult.Type.MISS)
            this.tasks.removeTask(followTask);

        if(result.typeOfHit == RayTraceResult.Type.BLOCK) {
            BlockPos pos = new BlockPos(result.hitVec);
            this.tasks.addTask(0, launhTask = new EntityAITargetBlock(this, 2.0D, Integer.MAX_VALUE, pos));
        }
        else if(result.typeOfHit == RayTraceResult.Type.ENTITY && result.entityHit instanceof EntityLivingBase)
            this.tasks.addTask(0, entityLaunchTask = new EntityAITargetEntity(this, false, (EntityLivingBase) result.entityHit));

        this.stepHeight = 0;
        this.startPosition = new BlockPos(this.getPositionVector());

        //play sound
    }

    @Override
    public EntityAgeable createChild(EntityAgeable ageable) {
        return null;
    }

    @Override
    public boolean canBeCollidedWith(){
        return false;
    }

    @Override
    public void onCollideWithPlayer(EntityPlayer player){
        if(player == owner){
            return;
        }
    }

    @Override
    public void collideWithEntity(Entity entity){

    }

    //@Override
    //protected PathNavigate getNewNavigator(World world){
        //return new PathNavigateFollowAbility(this, world);
    //}



    @Override
    public boolean processInteract(EntityPlayer player, EnumHand hand, ItemStack stack){
        if(hand.equals(EnumHand.MAIN_HAND)){

        }
        //remove task of following owner
        //add task of going to target
        //turn step height to 0
        //mark start position
        //play sound
        return true;
    }

    /**
     * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
     * use this to react to sunlight and start to burn.
     */
    public void onLivingUpdate()
    {
        super.onLivingUpdate();
        if (!this.onGround && this.motionY < 0.0D)
        {
            this.motionY *= 0.6D;
        }
        this.onGround = true; //to make the path navigate believe the entity is on the ground so it can execute
    }

    protected void updateAITasks()
    {
        //may not want them to fly high incase they get in the way of shooting abilities
        super.updateAITasks();

        --this.heightOffsetUpdateTime;

        if (this.heightOffsetUpdateTime <= 0)
        {
            this.heightOffsetUpdateTime = 100;
            this.heightOffset = 0.5F + (float)this.rand.nextGaussian() * 3.0F;
        }

        if (randomGeneratedOffset > 0 && owner != null && !owner.isDead && (Math.abs(this.posY - (owner.posY + owner.getEyeHeight())) > 1.0D))
        {
            this.motionY += (0.30000001192092896D - this.motionY) * 0.30000001192092896D;
            this.motionY *= randomGeneratedOffset;
            this.isAirBorne = true;
        }
        this.onGround = true; //to make the path navigate believe the entity is on the ground so it can execute
    }

    public void fall(float distance, float damageMultiplier)
    {
    }

    @Override
    public boolean isAIDisabled(){return false;}

    protected SoundEvent getAmbientSound(){
        return TestSounds.Guard;
    }
    protected SoundEvent getHurtSound(){return TestSounds.Guard;}
    protected SoundEvent getDeathSound(){return TestSounds.Guard;}


}

Link to comment
Share on other sites

You need to create a custom packet and send it to the server where it handles the spawning of the rock.

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.

Link to comment
Share on other sites

For anyone that happens to come across this same problem, just make sure that you registered your event class common/server side and not specifically just client side. Mine was fixed (well, believed to be fixed - I'll update the code tomorrow) by making sure it was registered common/server side.

Link to comment
Share on other sites

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...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

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