Jump to content

[1.15.2] Questions about projectile entity variables and NBT


xanderindalzone

Recommended Posts

Hi, I just wanted to ask a few questions about some code I made to know if it's not broken or anything.

At the moment its working just fine in client, but I'm not sure if its ok for servers.

INGAME FOOTAGE - https://gyazo.com/0f0986ab65446078ea545b52fb2a876e

 

 

1. First, in my Gun class, when I shoot the bullet, since I'm creating a new bullet entity object everytime I shoot a bullet, is it ok to use dynamic variables that change along the way(in the PistolBulletEntity class)? 

 

PROJECTILE ENTITY CLASS - all the variables are modified at some point(not all of them atm)

Quote

public class PistolBulletEntity extends AbstractArrowEntity 
{
    
    
    //HIT BOOLEANS
    public boolean IRON_HIT=false;
    public boolean GLASS_HIT=false;
    
    //PROJECTILE PROPERTIES
    public float bullet_damage=0;
    private boolean hasFirstUpdated=false;
    public double initPosX;
    public double initPosY;
    public double initPosZ;
    public PlayerEntity shooter;
    
    public PistolBulletEntity(EntityType<? extends AbstractArrowEntity> type, World worldIn) 
    {
        super(type, worldIn);
        setNoGravity(true);
    }
    public PistolBulletEntity(EntityType<? extends AbstractArrowEntity> type, LivingEntity shooter, World worldIn) 
    {
        super(type, shooter, worldIn);
        setNoGravity(true);
    }
    public PistolBulletEntity(EntityType<? extends AbstractArrowEntity> type, double x, double y, double z, World worldIn) 
    {
        super(type, x, y, z, worldIn);
        setNoGravity(true);
    }
    public PistolBulletEntity(EntityType<? extends AbstractArrowEntity> type, double x, double y, double z, World worldIn, PlayerEntity shooter, float damage) 
    {
        super(type, x, y, z, worldIn);
        this.bullet_damage=damage;
        this.shooter=shooter;
        setNoGravity(true);
    }
    

    

    
    @Override
    public IPacket<?> createSpawnPacket() 
    {
        return NetworkHooks.getEntitySpawningPacket(this);
    }
    
    @Override
    protected ItemStack getArrowStack() 
    {
        return new ItemStack(InitItems.BULLET_CAL_45.get()); //Init.BULLET_CAL_45 OLD
    }
    
//==========================================================================================================
//==========================================================================================================    
    public void setBulletDamage(float damage)
    {
        this.bullet_damage=damage;
    }
    
    @Override
    public Entity getShooter() 
    {
        return this.shooter;
    }
    
    @Override
    protected void onHit(RayTraceResult result) {
        if(result.getType() == RayTraceResult.Type.ENTITY)
        {
            EntityRayTraceResult entityResult = (EntityRayTraceResult) result;
            if(entityResult.getEntity() instanceof LivingEntity) {
                LivingEntity entityHit = (LivingEntity) entityResult.getEntity();
                entityHit.attackEntityFrom(DamageSource.causeArrowDamage(this, entityHit), this.bullet_damage);
                
                if(entityHit.getHealth()<=0)
                {
                    if(this.shooter != null)
                    {
                        this.shooter.playSound(InitSounds.SOUND_hit_marker.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
                        this.shooter.playSound(InitSounds.SOUND_kill.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
                    }
                }
                else
                {
                    if(this.shooter != null)
                    {
                        this.shooter.playSound(InitSounds.SOUND_hit_marker.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
                    }
                }
                spawnBloodParticles(this.getPosX(), this.getPosY(), this.getPosZ());
                this.remove();
            }
        }
        if(result.getType() == RayTraceResult.Type.BLOCK)
        {
            spawnGroundParticles(this.getPosX(), this.getPosY(), this.getPosZ());
            this.world.playSound(null, this.getPosition(), InitSounds.SOUND_bullet_ground_impact.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
            this.remove();
        }
    }
    
    
    @Override
    public void tick() {
        super.tick();
        if(hasFirstUpdated==false) 
        {
            initPosX=this.getPosX();
            initPosY=this.getPosY();
            initPosZ=this.getPosZ();
            hasFirstUpdated=true;
        }
        
        if(this.world.isRemote)
        {
            if(!this.inGround)
            {
                this.world.addParticle(ParticleTypes.FLAME, this.getPosX(), this.getPosY(), this.getPosZ(), 0.0D, 0.0D, 0.0D);
            }
        }
    }
    
    
    private void spawnGroundParticles(double x, double y, double z)
    {
        for(int i=0; i<5; i++) {
            this.world.addParticle(ParticleTypes.CLOUD, x, y, z, (0.25-Math.random()*0.5)*0.3, (0.25-Math.random()*0.5)*0.3, (0.25-Math.random()*0.5)*0.3);
        }
    }
    
    private void spawnSparkParticles(double x, double y, double z)
    {
        for(int i=0; i<5; i++) {
            this.world.addParticle(ParticleTypes.CRIT, x+Math.random()*1, y+Math.random()*1, z+Math.random()*1, 1-Math.random()*2, 1-Math.random()*2, 1-Math.random()*2);
        }
    }
    
    private void spawnBloodParticles(double x, double y, double z)
    {
        for(int i=0; i<10; i++) {
            this.world.addParticle(ParticleTypes.TOTEM_OF_UNDYING, x, y, z, (1-Math.random()*2)*0.5, (1-Math.random()*2)*0.5, (1-Math.random()*2)*0.5);
        }
    }
    

}
 

 

GUN CLASS - shootGun method creates the projectile entity object:

Quote

public class Gun extends Item
{
    
    public int gun_mag;
    
    public GunTypes gun_type;
    public Item ammo_used;
    public float gun_damage;
    public float gun_accuracy;
    public float gun_recoil;
    public float gun_bullet_speed;
    public int gun_firing_rate;
    public int gun_reload_cooldown;
    public int gun_reload_cooldown_cock;
    public boolean gun_is_full_auto;

    public float zoom_fov;
    public double aim_sensitivity;

    private static final IItemPropertyGetter AIM_PROPERTY_GETTER = (stack, world, entity) -> {
          return stack.hasTag()&&stack.getTag().getBoolean("gun_property_is_aiming") == true ? 1.0F : 0.0F;
       };
    
    
    public Gun(Properties properties) {
        super(properties);
        
        
        this.addPropertyOverride(new ResourceLocation("aiming"), AIM_PROPERTY_GETTER);
        
    }
    
    

    
//==========================================================================================================
//COMPORTAMIENTOS DEL ITEM
    
    //CANCELAR ANIMACION DE SWING DEL ITEM
    @Override
    public boolean onEntitySwing(ItemStack stack, LivingEntity entity) {return true;}
    //CANCELA GOLPES A ENTITIES
    @Override
    public boolean onLeftClickEntity(ItemStack stack, PlayerEntity player, Entity entity){return true;}
    //CANCELA PODER ROMPER BLOQUES CON ESTE ITEM
    @Override
    public boolean canPlayerBreakBlockWhileHolding(BlockState state, World worldIn, BlockPos pos, PlayerEntity player){return false;}
    
    @Override
    public Multimap<String, AttributeModifier> getAttributeModifiers(EquipmentSlotType equipmentSlot) {
        Multimap<String, AttributeModifier> multimap = super.getAttributeModifiers(equipmentSlot);
        multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Tool modifier", 20, Operation.ADDITION));
        return multimap;
    }
    
    @Override
    public UseAction getUseAction(ItemStack stack) {
        // TODO Auto-generated method stub
        return UseAction.NONE;
    }
    
    @Override
    public int getUseDuration(ItemStack stack) 
    {
        if(this.gun_is_full_auto) {return 0;}
        else {return 72000;}
    }
    
    public void setAiming(ItemStack gunStack, boolean value) //1 = AIMING 
    {
        if(value) 
        {
            gunStack.getTag().putBoolean("gun_property_is_aiming", true);
        }
        else 
        {
            gunStack.getTag().putBoolean("gun_property_is_aiming", false);
        }
    }
    
//==========================================================================================================    
    

    @Override
    public void onPlayerStoppedUsing(ItemStack stack, World worldIn, LivingEntity entityLiving, int timeLeft) 
    {
        super.onPlayerStoppedUsing(stack, worldIn, entityLiving, timeLeft);
        //DO STUFF
        if(entityLiving instanceof PlayerEntity) 
        {
            PlayerEntity playerIn = (PlayerEntity) entityLiving;
        }
    }
    
    @Override
    public void onUse(World worldIn, LivingEntity livingEntityIn, ItemStack stack, int count) 
    {
        super.onUse(worldIn, livingEntityIn, stack, count);
        //DO STUFF WHEN USING ITEM
        if(livingEntityIn instanceof PlayerEntity) 
        {
            PlayerEntity playerIn = (PlayerEntity) livingEntityIn;
        }
    }
    
    @Override
    public void inventoryTick(ItemStack stack, World worldIn, Entity entityIn, int itemSlot, boolean isSelected) 
    {
        super.inventoryTick(stack, worldIn, entityIn, itemSlot, isSelected);
        //DO STUFF
    }
    
    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
        
        
        playerIn.setActiveHand(handIn);

//            playerIn.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.2);
//            System.out.println(playerIn.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getValue());

        
        if(playerIn.getHeldItemMainhand().getDamage()<this.gun_mag||playerIn.isCreative()) {
                    
            shootGun(worldIn, playerIn); //DISPARAR ARMA
            playerIn.getHeldItemMainhand().damageItem(1, playerIn, null);
            if(!(playerIn.getHeldItemMainhand().getDamage()<this.gun_mag||playerIn.isCreative())) 
            {            
                worldIn.playSound(null, playerIn.getPosition(), SoundEvents.BLOCK_ANVIL_PLACE, SoundCategory.PLAYERS, 1.0F, 3.0F);
            }
        }
        else 
        {
            worldIn.playSound(null, playerIn.getPosition(), InitSounds.SOUND_no_ammo_click.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
        }    
        return new ActionResult<ItemStack>(ActionResultType.FAIL, playerIn.getHeldItemMainhand());
    }
    
    

//===========================================================================================
//PRIVATE METHOD
//===========================================================================================
    private void shootGun(World worldIn, PlayerEntity playerIn) 
    {
        double posX = playerIn.getPosX();
        double posY = playerIn.getPosY();
        double posZ = playerIn.getPosZ();
        Vec3d look = playerIn.getLookVec();
        World world = playerIn.getEntityWorld();
            
        //=======================================================
        //PROPIEDADES DEL DISPARO
        //=======================================================
        PistolBulletEntity bullet = new PistolBulletEntity(InitEntities.PISTOL_BULLET_ENTITY.get(), 1.0D, 1.0D, 1.0D, world, playerIn, this.gun_damage);
        
        
        //ESTABLECE EL DAÑO DE LA BALA
//        bullet.setBulletDamage(this.gun_damage);
                
        //ESTABLECE EL ALCANCE DE LA BALA
        bullet.setVelocity(look.x*this.gun_bullet_speed, (look.y*this.gun_bullet_speed), look.z*this.gun_bullet_speed);
                
        //ESTABLECE LA CADENCIA DEL ARMA
        playerIn.getCooldownTracker().setCooldown(this, this.gun_firing_rate); //TICKS - 30 TICKS = 1 seg
                
        //ESTABLECE EL RETROCESO MAXIMO DEL DISPARO
        float recoil_pitch = (float) -(((gun_recoil)*Math.random()));    //ES SIEMPRE NEGATIVO, SIEMPRE TENDRA RETROCESO HACIA ARRIBA
        float recoil_yaw = (float) ((float) gun_recoil-((gun_recoil*2)*Math.random()));
        playerIn.rotationPitch=playerIn.rotationPitch+recoil_pitch;
        playerIn.rotationYaw=playerIn.rotationYaw+recoil_yaw;
        
        
        
        double sneakModifier = 0;
        if(playerIn.isSneaking()) {sneakModifier=0.1;}
        double bulletXPos = posX+(look.x*1.3D);
        double bulletYPos = posY+(look.y*1.5D)+1.6D+sneakModifier;
        double bulletZPos = posZ+(look.z*1.3D);
        
        //CONFIGURA LA ALTURA DE SALIDA DE LA BALA
        if(playerIn.rotationPitch>60) //SI ESTA MIRANDO HACIA ABAJO
        {
            bulletYPos = posY+(look.y*1.5D)+1.0D+sneakModifier;
        }
        if(playerIn.rotationPitch<-60) //SI ESTA MIRANDO HACIA ARRIBA
        {
            bulletYPos = posY+(look.y*1.5D)+1.3D+sneakModifier;
        }
        
        

        //SPAWNEAR FOGONAZO
        worldIn.addParticle(ParticleTypes.CLOUD, bulletXPos, bulletYPos, bulletZPos, 0.0D, 0.5D, 0.0D);
        
        //ESTABLECER POSICION INICIAL DE LA BALA
        bullet.setPosition(bulletXPos, bulletYPos, bulletZPos);

        if(!world.isRemote)
        {
            world.addEntity(bullet);
            shootingGunSound(worldIn, playerIn, this);
        }
        
        
    }


    private void shootingGunSound(World worldIn, PlayerEntity playerIn, Gun gun) 
    {
        if(gun instanceof Colt1911) 
        {
            worldIn.playSound(null, playerIn.getPosition(), InitSounds.SOUND_shot_Colt1911.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
        }
    }
    
    private void reloadingGunSound(World worldIn, PlayerEntity playerIn, Gun gun, boolean cock_reload) 
    {
        if(gun instanceof Colt1911) 
        {
            if(cock_reload)
            {
                worldIn.playSound(null, playerIn.getPosition(), InitSounds.SOUND_reload_Colt1911_cock.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
                playerIn.getCooldownTracker().setCooldown(InitItems.PISTOL_COLT_1911.get(), this.gun_reload_cooldown_cock); //TICKS - 30 TICKS = 1 seg
            }
            else
            {
                worldIn.playSound(null, playerIn.getPosition(), InitSounds.SOUND_reload_Colt1911.get(), SoundCategory.PLAYERS, 1.0F, 1.0F);
                playerIn.getCooldownTracker().setCooldown(InitItems.PISTOL_COLT_1911.get(), this.gun_reload_cooldown); //TICKS - 30 TICKS = 1 seg
            }
        }
    }
    
    
    
    
    
    //===========================================================================================
    //CALLED FROM CLIENT TO SERVER METHOD
    //===========================================================================================
    
    public boolean ReloadGun(World worldIn, PlayerEntity player) {
        int ammo_left = (this.gun_mag-player.getHeldItemMainhand().getDamage());    
        boolean cock_reload = false;
        
                
        //COMPRUEBA SI EL CARGADOR SE PUEDE RECARGAR
        if(ammo_left!=this.gun_mag&&!player.isCreative())    
        {
            if(ammo_left==0) {cock_reload=true;}
                    
                    
            //COMPRUEBA SI EL JUGADOR TIENE MUNICION EN EL INVENTARIO
            if(player.inventory.hasItemStack(new ItemStack(this.ammo_used))) 
            {
                for(int slotIndex=0; slotIndex<player.inventory.mainInventory.size(); slotIndex++) 
                {
                    int ammo_needed = this.gun_mag-ammo_left;
                    ItemStack item = player.inventory.getStackInSlot(slotIndex).copy();
                    if(item.getItem() == this.ammo_used)
                    {
                        if(!worldIn.isRemote) 
                        {
                            ammo_left=removeAmmo(player, ammo_needed, ammo_left, item, slotIndex);
                        }
                        else
                        {
                            ammo_left=removeAmmo(player, ammo_needed, ammo_left, item, slotIndex);
                        }
                        reloadingGunSound(worldIn, player, this, cock_reload);
                    }
                }
                return true;
            }
        }
        return false;
    }
        
    //DEVUELVE LA MUNICION QUE FALTA
    private int removeAmmo(PlayerEntity player, int ammo_needed, int ammo_left, ItemStack item, int slotIndex)
    {
        if(ammo_needed<item.getCount())
        {
            item.shrink(ammo_needed);
            player.inventory.setInventorySlotContents(slotIndex, item);
            player.getHeldItemMainhand().damageItem(-ammo_needed, player, null);
            ammo_left=this.gun_mag;
        }
        else
        {
            player.inventory.setInventorySlotContents(slotIndex, new ItemStack(Blocks.AIR));
            player.getHeldItemMainhand().damageItem(-item.getCount(), player, null);
            ammo_left=ammo_left+item.getCount();
        }
        return ammo_left;
    }

    
}
 

 

 

 

 

 

 

2. To make the Gun render in Aim position I'm using NBT tags, but since its the first time i'm using them i wanted to know if they're well implemented.

I'm also using static dynamic variables in the client event class to tell the code when the player is aiming etc etc, to apply sensitivity and fov changes when aiming, but i dont 100% know if thats ok, i supposed it was ok because it was a client only event handler.

 

The event that handles aiming sends a packet to server to add an NBT value to the Gun ItemStack with the key ("property_gun_is_aiming") which then is used in the Gun override property to change the model ingame. I learned addPropertyOverride by checking the code from the Bow class.

 

CLIENT KEY EVENT CLASS

Quote

@Mod.EventBusSubscriber(modid = CustomGunsMod.MOD_ID, bus = Bus.FORGE, value = Dist.CLIENT)
public class ClientKeyEvents 
{

    public static double previous_FOV=0;
    public static double previous_sensitivity=0;
    public static boolean is_Aiming=false;
    
    
    
    
    
    /**
     * Displays the Gun Ammo in the gun held by the player
     * @param event
     */
    @SubscribeEvent
    public static void displayGunStatus(RenderGameOverlayEvent.Text event) {
        PlayerEntity player = Minecraft.getInstance().player;
        int yd = event.getWindow().getScaledHeight();
        int xd = event.getWindow().getScaledWidth();
        int x=(int) (xd*0.01);
        int y=(int) (yd*0.65);
        int x2=(int) (xd*0.42);
        int y2=(int) (yd*0.7);
        if(Minecraft.getInstance().player.getHeldItemMainhand().getItem() instanceof Gun)
        {
            Gun gun = (Gun) player.getHeldItemMainhand().getItem();
            FontRenderer TextRenderer = Minecraft.getInstance().fontRenderer;
            String text = "Gun AMMO: ";
            String textAmmo = "["+(gun.gun_mag-player.getHeldItemMainhand().getDamage())+"/"+gun.gun_mag+"]";
            if(!player.isCreative()) 
            {
                if(!((gun.gun_mag-player.getHeldItemMainhand().getDamage())>0))
                {
                    String text1="No AMMO!";
                    String text2="Press "+InitKeys.KEY_RELOAD_GUN.getLocalizedName().toUpperCase()+" to reload!";
                    TextRenderer.drawStringWithShadow(text1, x+10, y+20, 16730698);
                    TextRenderer.drawStringWithShadow(text2, x+10, y+30, 16777215);        
                }
                if(player.getCooldownTracker().hasCooldown(gun)) 
                {
                    
                    String text3="Reloading!";
                    //System.out.println(text3);
                    TextRenderer.drawStringWithShadow(text3, x2+10, y2, 61256);
                }
            }
            else 
            {
                textAmmo = "[oo/"+gun.gun_mag+"]";
            }
            TextRenderer.drawStringWithShadow(text, x+10, y, 16777215);
            TextRenderer.drawStringWithShadow(textAmmo, x+10, y+10, 16245549);
        }
    }
    
    
    @SubscribeEvent
    public static void AimGun(RenderHandEvent event)
    {    
        if(Minecraft.getInstance().gameSettings.keyBindAttack.isKeyDown()
                &&Minecraft.getInstance().player.getHeldItemMainhand().getItem() instanceof Gun)
        {
            
            Gun gun = (Gun) Minecraft.getInstance().player.getHeldItemMainhand().getItem();
            
            if(!is_Aiming) {
                previous_FOV = Minecraft.getInstance().gameSettings.fov;
                previous_sensitivity = Minecraft.getInstance().gameSettings.mouseSensitivity;
                Minecraft.getInstance().gameSettings.fov=gun.zoom_fov;
                Minecraft.getInstance().gameSettings.mouseSensitivity=gun.aim_sensitivity;
                is_Aiming=true;
                PacketHandler.channel.sendToServer(new AimGunMessage(is_Aiming));
            }
        }
        else
        {
            if(is_Aiming) 
            {
                Minecraft.getInstance().gameSettings.fov=previous_FOV;
                Minecraft.getInstance().gameSettings.mouseSensitivity=previous_sensitivity;
                is_Aiming=false;
                PacketHandler.channel.sendToServer(new AimGunMessage(is_Aiming));
            }
        }
    }
    
    
//====================================================================
//CLIENT EVENTS TO SERVER
//====================================================================    
    
    @SubscribeEvent
    public static void ReloadGunPacketToServer(InputEvent event) 
    {
        if(InitKeys.KEY_RELOAD_GUN.isPressed())
        {
            //SEND PACKET TO SERVER
            PacketHandler.channel.sendToServer(new ReloadGunMessage());
        }
    }
    
    
    
    
}

 

 

And thats all, I would love to know if its ok so I can continue. If its not ok, how could I fix it? thx.

Link to comment
Share on other sites

(Sorry I wasnt active)

 

 

On 7/23/2020 at 10:54 PM, poopoodice said:

but it seems like you forgot to save them.

What do you mean by saving them? And how could I do this?

 

 

On 7/23/2020 at 10:54 PM, poopoodice said:

instead of using RenderHandEvent, use ClientTickEvent.

I had that event because I was trying another thing before, I'll change it now, thx for noticing XD

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.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • https://pastebin.com/VwpAW6PX My game crashes upon launch when trying to implement the Oculus mod to this mod compilation, above is the crash report, I do not know where to begin to attempt to fix this issue and require assistance.
    • https://youtube.com/shorts/gqLTSMymgUg?si=5QOeSvA4TTs-bL46
    • CubeHaven is a SMP server with unique features that can't be found on the majority of other servers! Java: MC.CUBEHAVEN.NET Bedrock: MC.CUBEHAVEN.NET:19132 3 different stores: - CubeHaven Store: Our store to purchase using real money. - Bitcoin Store: Store for Bitcoin. Bitcoin can be earned from playing the server. Giving options for players if they want to spend real money or grind to obtain exclusive packages. - Black Market: A hidden store for trading that operates outside our traditional stores, like custom enchantments, exclusive items and more. Some of our features include: Rank Up: Progress through different ranks to unlock new privileges and perks. 📈 Skills: RPG-style skill system that enhances your gaming experience! 🎮 Leaderboards: Compete and shine! Top players are rewarded weekly! 🏆 Random Teleporter: Travel instantly across different worlds with a click! 🌐 Custom World Generation: Beautifully generated world. 🌍 Dungeons: Explore challenging and rewarding dungeons filled with treasures and monsters. 🏰 Kits: Unlock ranks and gain access to various kits. 🛠️ Fishing Tournament: Compete in a friendly fishing tournament! 🎣 Chat Games: Enjoy games right within the chat! 🎲 Minions: Get some help from your loyal minions. 👥 Piñata Party: Enjoy a festive party with Piñatas! 🎉 Quests: Over 1000 quests that you can complete! 📜 Bounty Hunter: Set a bounty on a player's head. 💰 Tags: Displayed on nametags, in the tab list, and in chat. 🏷️ Coinflip: Bet with other players on coin toss outcomes, victory, or defeat! 🟢 Invisible & Glowing Frames: Hide your frames for a cleaner look or apply a glow to it for a beautiful look. 🔲✨[ Player Warp: Set your own warp points for other players to teleport to. 🌟 Display Shop: Create your own shop and sell to other players! 🛒 Item Skins: Customize your items with unique skins. 🎨 Pets: Your cute loyal companion to follow you wherever you go! 🐾 Cosmetics: Enhance the look of your character with beautiful cosmetics! 💄 XP-Bottle: Store your exp safely in a bottle for later use! 🍶 Chest & Inventory Sorting: Keep your items neatly sorted in your inventory or chest! 📦 Glowing: Stand out from other players with a colorful glow! ✨ Player Particles: Over 100 unique particle effects to show off. 🎇 Portable Inventories: Over virtual inventories with ease. 🧳 And a lot more! Become part of our growing community today! Discord: https://cubehaven.net/discord Java: MC.CUBEHAVEN.NET Bedrock: MC.CUBEHAVEN.NET:19132
    • # Problematic frame: # C [libopenal.so+0x9fb4d] It is always the same issue - this refers to the Linux OS - so your system may prevent Java from working   I am not familiar with Linux - check for similar/related issues  
  • Topics

×
×
  • Create New...

Important Information

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