-
Posts
867 -
Joined
-
Last visited
-
Days Won
3
Everything posted by JimiIT92
-
Don't know if this will work, but you can try overriding BlockItem, override the method hasEffect to return true in that class and use that to register the block item
-
I'm trying to change the displayed name color of a tile entity. By default the game renders it in dark gray, as you can see in the image, but i want it to be white. Since in the ```GameRenderer.drawNameplate``` method appearently you can't pass the color as argument, i've tried to override the internal method in the tile entity code instead, by doing this package com.antiblaze.entities.renderers; import com.antiblaze.entities.tileentity.AntiBedrockTileEntity; import com.antiblaze.settings.Settings; import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; /** * AntiBedrock TileEntity Renderer */ @OnlyIn(Dist.CLIENT) public class AntiBedrockTileEntityRenderer extends TileEntityRenderer<AntiBedrockTileEntity> { /** * Render the Tile Entity * @param tileEntityIn AntiBedrock Tile Entity * @param x TileEntity X Position * @param y TileEntity Y Position * @param z TileEntity Z Position * @param partialTicks TileEntity Partial Ticks * @param destroyStage TileEntity Destroy Stages */ public void render(AntiBedrockTileEntity tileEntityIn, double x, double y, double z, float partialTicks, int destroyStage) { if(tileEntityIn.getDonator() != null) { ActiveRenderInfo activerenderinfo = this.rendererDispatcher.renderInfo; double d0 = tileEntityIn.getDistanceSq(activerenderinfo.getProjectedView().x, activerenderinfo.getProjectedView().y, activerenderinfo.getProjectedView().z); if (!(d0 > (double)(Settings.BEDROCK_NAME_RANGE.get() * Settings.BEDROCK_NAME_RANGE.get()))) { float f = activerenderinfo.getYaw(); float f1 = activerenderinfo.getPitch(); drawNameplate(this.getFontRenderer(), tileEntityIn.getDonator(), (float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F, 0, f, f1, false, 0xFFFFFF); } } } public static void drawNameplate(FontRenderer fontRendererIn, String str, float x, float y, float z, int verticalShift, float viewerYaw, float viewerPitch, boolean isSneaking, int color) { GlStateManager.pushMatrix(); GlStateManager.translatef(x, y, z); GlStateManager.normal3f(0.0F, 1.0F, 0.0F); GlStateManager.rotatef(-viewerYaw, 0.0F, 1.0F, 0.0F); GlStateManager.rotatef(viewerPitch, 1.0F, 0.0F, 0.0F); GlStateManager.scalef(-0.025F, -0.025F, 0.025F); GlStateManager.disableLighting(); GlStateManager.depthMask(false); if (!isSneaking) { GlStateManager.disableDepthTest(); } GlStateManager.enableBlend(); GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); int i = fontRendererIn.getStringWidth(str) / 2; GlStateManager.disableTexture(); Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferbuilder = tessellator.getBuffer(); bufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR); float f = Minecraft.getInstance().gameSettings.func_216840_a(0.25F); bufferbuilder.pos((double)(-i - 1), (double)(-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, f).endVertex(); bufferbuilder.pos((double)(-i - 1), (double)(8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, f).endVertex(); bufferbuilder.pos((double)(i + 1), (double)(8 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, f).endVertex(); bufferbuilder.pos((double)(i + 1), (double)(-1 + verticalShift), 0.0D).color(0.0F, 0.0F, 0.0F, f).endVertex(); tessellator.draw(); GlStateManager.enableTexture(); if (!isSneaking) { fontRendererIn.drawString(str, (float)(-fontRendererIn.getStringWidth(str) / 2), (float)verticalShift, color); GlStateManager.enableDepthTest(); } GlStateManager.depthMask(true); fontRendererIn.drawString(str, (float)(-fontRendererIn.getStringWidth(str) / 2), (float)verticalShift, isSneaking ? color : -1); GlStateManager.enableLighting(); GlStateManager.disableBlend(); GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.popMatrix(); } } But the nameplate still draws as before https://imgur.com/t778Q0F So how can i change this color to be whatever color i want? EDIT: Solved by implementing the INameable interface in the tile entity
-
[1.14.4][SOLVED] TileEntity not working properly
JimiIT92 replied to JimiIT92's topic in Modder Support
Update: what i noticed is that if i set the block with the command, then relog in the world the name appears. So i guess is an entity client updating not firing? -
I made a block with a TileEntity in it wich stores the block custom name. For instance, if you rename the block "Test" in the Anvil an then place it, the block will display a nameplate on it with the name you set (test in this case). However i'm trying to make it working with the /setblock command too, but what happens is that the block is placed but the tile entity has no name. I'm trying using this command /setblock ~ ~ ~ antiblaze:bedrock{Donator:"\"Test from command\""} replace Also the text rendered is black for some reason https://imgur.com/ywK3ZhG This is the block code package com.antiblaze.blocks; import com.antiblaze.entities.tileentity.AntiBedrockTileEntity; import com.antiblaze.settings.Settings; import net.minecraft.block.BedrockBlock; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; import javax.annotation.Nullable; /** * AntiBlaze Bedrock Block * @author JimiIT92 */ public class AntiBlazeBedrockBlock extends BedrockBlock { /** * Initialize the AntiBlaze Bedrock Block */ public AntiBlazeBedrockBlock() { super(Properties.from(Blocks.BEDROCK).hardnessAndResistance(-1.0F, 3600000.0F).noDrops()); setRegistryName(Settings.MODID,"bedrock"); } /** * If this block has a TileEntity * @param state Block State * @return True */ @Override public boolean hasTileEntity(BlockState state) { return true; } /** * Create a default Tile Entity for this block * @param state Block State * @param world World Instance * @return AntiBedrockTileEntity instance */ @Nullable @Override public TileEntity createTileEntity(BlockState state, IBlockReader world) { return new AntiBedrockTileEntity(); } /** * Set the TileEntity name when the block is placed * @param worldIn World Instance * @param pos Block Position * @param state Block State * @param placer Block Placer * @param stack Block's Item Stack */ @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { TileEntity tileEntity = worldIn.getTileEntity(pos); if(tileEntity instanceof AntiBedrockTileEntity && stack != null && stack.hasDisplayName()) { ((AntiBedrockTileEntity) tileEntity).setDonator(stack.getDisplayName().getString()); } super.onBlockPlacedBy(worldIn, pos, state, placer, stack); } } This is the TileEntity Block package com.antiblaze.entities.tileentity; import com.antiblaze.core.AntiBlazeEntities; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; /** * AntiBedrock Tile Entity * @author JimiIT92 */ public class AntiBedrockTileEntity extends TileEntity { /** * NBT Donator Key */ private final String NBT_KEY = "Donator"; /** * AntiBedrock TileEntity stored donator */ private String donator; /** * AntiBedrock TileEntity constructor */ public AntiBedrockTileEntity() { super(AntiBlazeEntities.ANTIBEDROCK_TILE_ENTITY); } /** * Set the AntiBedrock TileEntity donator * @param donator Donator Name */ public void setDonator(String donator) { this.donator = donator; } /** * Get the AntiBedrock TileEntity donator * @return AntiBedrock TileEntity donator */ public String getDonator() { return this.donator; } /** * Writhe the AntiBedrock TileEntity donator name to NBT * @param compound NBT Compound * @return NBT Compound */ @Override public CompoundNBT write(CompoundNBT compound) { if(this.donator != null) { compound.putString(NBT_KEY, this.donator); } return super.write(compound); } /** * Read the Donator name from the NBT Compound * @param compound NBT Compound */ @Override public void read(CompoundNBT compound) { super.read(compound); this.donator = compound.getString(NBT_KEY); } /** * Get the NBT Update Tag * @return NBT Update Tag */ @Override public CompoundNBT getUpdateTag() { return write(super.getUpdateTag()); } /** * Handle the NBT Update Tag * @param tag NBT Update Tag */ @Override public void handleUpdateTag(CompoundNBT tag) { read(tag); } } And this is the Renderer class package com.antiblaze.entities.renderers; import com.antiblaze.entities.tileentity.AntiBedrockTileEntity; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; /** * AntiBedrock TileEntity Renderer */ @OnlyIn(Dist.CLIENT) public class AntiBedrockTileEntityRenderer extends TileEntityRenderer<AntiBedrockTileEntity> { /** * Render the Tile Entity * @param tileEntityIn AntiBedrock Tile Entity * @param x TileEntity X Position * @param y TileEntity Y Position * @param z TileEntity Z Position * @param partialTicks TileEntity Partial Ticks * @param destroyStage TileEntity Destroy Stages */ public void render(AntiBedrockTileEntity tileEntityIn, double x, double y, double z, float partialTicks, int destroyStage) { if(tileEntityIn.getDonator() != null) { super.drawNameplate(tileEntityIn, tileEntityIn.getDonator(), x, y, z, 32); } } } What should i change to make it work with commands or make the text white? EDIT: Solved by adding these two methods in the TileEntity code @Nullable @Override public SUpdateTileEntityPacket getUpdatePacket() { CompoundNBT nbt = new CompoundNBT(); nbt.putString(NBT_KEY, this.donator); return new SUpdateTileEntityPacket(getPos(), 1, nbt); } @Override public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) { CompoundNBT nbt = pkt.getNbtCompound(); this.donator = nbt.getString(NBT_KEY); }
-
Doing right now ?? EDIT: I've seen this PR that is similar to the issue https://github.com/MinecraftForge/MinecraftForge/pull/2118 Maybe i'll just update that to report that is occurring with latest version?
-
Tried with the latest forge mdk version (28.0.102), it still drops the item if i don't manually register the dispense behavior
-
Got it, i misinterpreted the question. But by looking at the fact that manually registering the behavior it works i guess this is the case, the behavior is not registered when the spawn egg is registered. Is there something wrong in how or where i register the egg?
-
BTW by doing this after registering the egg items it works DefaultDispenseItemBehavior spawnEggItemBehavior = new DefaultDispenseItemBehavior() { public ItemStack dispenseStack(IBlockSource source, ItemStack stack) { Direction direction = source.getBlockState().get(DispenserBlock.FACING); ((SpawnEggItem)stack.getItem()).getType(stack.getTag()).spawn(source.getWorld(), stack, null, source.getBlockPos().offset(direction), SpawnReason.DISPENSER, direction != Direction.UP, false); stack.shrink(1); return stack; } }; DispenserBlock.registerDispenseBehavior(AntiBlazeItems.BLAZE_BAT_SPAWN_EGG, spawnEggItemBehavior); I don't know if this is intended or not, at least if so i guess there should be a spawn egg item behavior property available
-
I've launched the client in debug, setting breakpoints in the SpawnEggItem.getEggs() method and in the createSpawnEgg method. The call stack is this SpawnEggItem.getEggs(): EGGS size here is 58 createSpawnEgg for every entity i'm registering (2) SpawnEggItem.getEggs(): EGGS size here is 60 So i guess the Entities are registered to the EGGS field of the SpawnEggItem...
-
As the title said i thought that if i put a spawn egg inside the Dispenser and then activate the Dispenser, this will spawn the mob. However the dispenser is dropping the egg as a normal item. Is there a directive to tell Minecraft to spawn the entity relative to the egg from dispenser or should i implement a custom dispense behaviour? This is how i register the eggs @SubscribeEvent public static void onEntitySpawnEggRegistry(final RegistryEvent.Register<Item> event) { event.getRegistry().registerAll( AntiBlazeItems.BLAZE_BAT_SPAWN_EGG = AntiBlazeEntities.createEntitySpawnEgg(AntiBlazeEntities.BLAZE_BAT, 0xFFF847, 0x8B3401, "blaze_bat_spawn_egg"), AntiBlazeItems.STRAY_BAT_SPAWN_EGG = AntiBlazeEntities.createEntitySpawnEgg(AntiBlazeEntities.STRAY_BAT, 0x5A8A94, 0xDEF1F6, "stray_bat_spawn_egg") ); } And this is the createEntitySpawnEgg function public static Item createEntitySpawnEgg(EntityType<?> entity, int primaryColor, int secondaryColor, String name) { SpawnEggItem spawnEgg = new SpawnEggItem(entity, primaryColor, secondaryColor, new Item.Properties().group(ItemGroup.MISC)); spawnEgg.setRegistryName(name); return spawnEgg; } If you want to take a deeper look into the source code you can find the repository here https://github.com/JimiIT92/AntiblazeMod
-
I'm trying to make two mobs, that are similar to Bats, but that will fight each others. The mob itself works fine, however their AI is a bit clunky. When there are many of them they fight each other and is fine, but when there are just few of them, like for instance a 5v5 situation, they just stare at each others. What i'm trying to do is that they constantly fight each others until there is no member of the other mob alive. This is the repository for the Code i'm using https://github.com/JimiIT92/AntiblazeMod I really can't understand why this happen since the AI Goal code is pretty much a copy of the Zombie Attack player code
-
Thank you, it works now
-
I've created a new mob by essentially copying the Bat and removing it's wings. The mob works fine, however the mob's hitbox is too large compared to the Bat. In the picture you can see the difference Image here This is the model class i'm using package com.antiblaze.entities.models; import com.antiblaze.entities.AntiBlazeEntity; import net.minecraft.client.renderer.entity.model.EntityModel; import net.minecraft.client.renderer.entity.model.RendererModel; import net.minecraft.util.math.MathHelper; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; /** * AntiBlaze Model * @author JimiIT92 */ @OnlyIn(Dist.CLIENT) public class AntiBlazeModel<T extends AntiBlazeEntity> extends EntityModel<T> { /** * AntiBlaze Head Model */ private final RendererModel antiBlazeHead; /** * AntiBlaze Body Model */ private final RendererModel antiBlazeBody; /** * Constructor. Initialize the Model */ public AntiBlazeModel() { this.textureWidth = 64; this.textureHeight = 64; this.antiBlazeHead = new RendererModel(this, 0, 0); this.antiBlazeHead.addBox(-3.0F, -3.0F, -3.0F, 6, 6, 6); RendererModel renderermodel = new RendererModel(this, 24, 0); renderermodel.addBox(-4.0F, -6.0F, -2.0F, 3, 4, 1); this.antiBlazeHead.addChild(renderermodel); RendererModel renderermodel1 = new RendererModel(this, 24, 0); renderermodel1.mirror = true; renderermodel1.addBox(1.0F, -6.0F, -2.0F, 3, 4, 1); this.antiBlazeHead.addChild(renderermodel1); this.antiBlazeBody = new RendererModel(this, 0, 16); this.antiBlazeBody.addBox(-3.0F, 4.0F, -3.0F, 6, 12, 6); this.antiBlazeBody.setTextureOffset(0, 34).addBox(-5.0F, 16.0F, 0.0F, 10, 6, 1); } /** * Render the Model * @param entityIn Entity to render * @param limbSwing Limb Swing * @param limbSwingAmount Limb Swing Amount * @param ageInTicks Age in Ticks * @param netHeadYaw Net Head Yea * @param headPitch Head Pitch * @param scale Scale */ public void render(T entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale) { this.setRotationAngles(entityIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale); this.antiBlazeHead.render(scale); this.antiBlazeBody.render(scale); } /** * Set Model rotation and angles * @param entityIn Entity to render * @param limbSwing Limb Swing * @param limbSwingAmount Limb Swing Amount * @param ageInTicks Age in Ticks * @param netHeadYaw Net Head Yea * @param headPitch Head Pitch * @param scale Scale */ public void setRotationAngles(T entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale) { this.antiBlazeHead.rotateAngleX = headPitch * ((float)Math.PI / 180F); this.antiBlazeHead.rotateAngleY = netHeadYaw * ((float)Math.PI / 180F); this.antiBlazeHead.rotateAngleZ = 0.0F; this.antiBlazeHead.setRotationPoint(0.0F, 0.0F, 0.0F); this.antiBlazeBody.rotateAngleX = ((float)Math.PI / 4F) + MathHelper.cos(ageInTicks * 0.1F) * 0.15F; this.antiBlazeBody.rotateAngleY = 0.0F; } } This is the entity class package com.antiblaze.entities; import com.antiblaze.entities.goals.AntiBlazeAttackGoal; import com.antiblaze.settings.Settings; import net.minecraft.block.BlockState; import net.minecraft.entity.*; import net.minecraft.entity.passive.AmbientEntity; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.DamageSource; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; /** * AntiBlaze Entity * @author JimiIT92 */ public class AntiBlazeEntity extends AmbientEntity { /** * Entity Spawn Position */ private BlockPos spawnPosition; /** * Constructor. Initialize the AntiBlaze Entity * @param type Entity Type * @param world World Instance */ public AntiBlazeEntity(EntityType<? extends AmbientEntity> type, World world) { super(type, world); } /** * Register the AntiBlaze Goals */ @Override protected void registerGoals() { super.registerGoals(); this.goalSelector.addGoal(Settings.ATTACK_GOAL_PRIORITY, new AntiBlazeAttackGoal(this, Settings.ATTACK_GOAL_SPEED, false)); } /** * Register the AntiBlaze attributes */ @Override protected void registerAttributes() { super.registerAttributes(); this.getAttributes().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE); this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(6.0D); this.getAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(Settings.ATTACK_DAMAGE.get()); } /** * Returns the volume for the sounds this mob makes. * @return Mob's sound volume */ @Override protected float getSoundVolume() { return 0.1F; } /** * Gets the pitch of living sounds in living entities. * @return Mob's pitch */ @Override protected float getSoundPitch() { return super.getSoundPitch() * 0.95F; } /** * Returns whether this entity should push and be pushed by other entities when colliding. * @return True if the entity should push and be pushed by other entities when colliding, false otherwise */ @Override public boolean canBePushed() { return false; } /** * Called on collision with an entity. Does nothing * @param entityIn Entity */ protected void collideWithEntity(Entity entityIn) { } /** * Called on collision with nearest entity. Does nothing */ protected void collideWithNearbyEntities() { } /** * Called to update the entity's position/logic */ @Override public void tick() { super.tick(); this.setMotion(this.getMotion().mul(1.0D, 0.6D, 1.0D)); } /** * Update the AI Tasks */ @Override protected void updateAITasks() { super.updateAITasks(); if (this.spawnPosition != null && (!this.world.isAirBlock(this.spawnPosition) || this.spawnPosition.getY() < 1)) { this.spawnPosition = null; } if (this.spawnPosition == null || this.rand.nextInt(30) == 0 || this.spawnPosition.withinDistance(this.getPositionVec(), 2.0D)) { this.spawnPosition = new BlockPos(this.posX + (double)this.rand.nextInt(7) - (double)this.rand.nextInt(7), this.posY + (double)this.rand.nextInt(6) - 2.0D, this.posZ + (double)this.rand.nextInt(7) - (double)this.rand.nextInt(7)); } double d0 = (double)this.spawnPosition.getX() + 0.5D - this.posX; double d1 = (double)this.spawnPosition.getY() + 0.1D - this.posY; double d2 = (double)this.spawnPosition.getZ() + 0.5D - this.posZ; Vec3d vec3d = this.getMotion(); Vec3d vec3d1 = vec3d.add((Math.signum(d0) * 0.5D - vec3d.x) * (double)0.1F, (Math.signum(d1) * (double)0.7F - vec3d.y) * (double)0.1F, (Math.signum(d2) * 0.5D - vec3d.z) * (double)0.1F); this.setMotion(vec3d1); float f = (float)(MathHelper.atan2(vec3d1.z, vec3d1.x) * (double)(180F / (float)Math.PI)) - 90.0F; float f1 = MathHelper.wrapDegrees(f - this.rotationYaw); this.moveForward = 0.5F; this.rotationYaw += f1; } /** * Returns whether this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to * prevent them from trampling crops * @return True if the entity will trigger Block.onEntityWalking, false otherwise */ @Override protected boolean canTriggerWalking() { return false; } /** * Return whether this entity should not trigger a pressure plate or a tripwire. * @return True if the entity should not trigger a pressure plate or a tripwire, false otherwise */ public boolean doesEntityNotTriggerPressurePlate() { return true; } /** * Called on entity falling. Does nothing * @param distance Fall distance * @param damageMultiplier Damage Multiplier */ public void fall(float distance, float damageMultiplier) { } /** * Update Fall State. Does nothing * @param y Pos Y * @param onGroundIn If is on ground * @param state BlockState the entity is falling * @param pos BlockPos the entity is falling */ protected void updateFallState(double y, boolean onGroundIn, BlockState state, BlockPos pos) { } /** * Called when the entity is attacked. * @param source Damage Source * @param amount Damage Amount * @return True if the entity should be damaged, false otherwise */ @Override public boolean attackEntityFrom(DamageSource source, float amount) { if(this.isInvulnerableTo(source)) { return false; } return super.attackEntityFrom(source, amount); } /** * (abstract) Protected helper method to read subclass entity data from NBT. * @param compound NBTTag Compound */ @Override public void readAdditional(CompoundNBT compound) { super.readAdditional(compound); } /** * (abstract) Protected helper method to write subclass entity data to NBT. * @param compound NBTTag Compound */ @Override public void writeAdditional(CompoundNBT compound) { super.writeAdditional(compound); } /** * Get the entity's eye height * @param poseIn Entity's pose * @param sizeIn Enttiy Size * @return Entity Eye Height */ protected float getStandingEyeHeight(Pose poseIn, EntitySize sizeIn) { return sizeIn.height / 2.0F; } } and this is how i render package com.antiblaze.entities.renderers; import com.antiblaze.entities.AntiBlazeEntity; import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.renderer.entity.MobRenderer; import net.minecraft.client.renderer.entity.model.EntityModel; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; /** * AntiBlaze Rendered Class * @author JimiIT92 */ @OnlyIn(Dist.CLIENT) public class AntiBlazeRenderer<T extends AntiBlazeEntity, M extends EntityModel<T>> extends MobRenderer<T, M> { /** * Constructor. Initialize the Render Manager * @param renderManagerIn Render Manager */ public AntiBlazeRenderer(EntityRendererManager renderManagerIn, M model) { super(renderManagerIn, model, 0.25F); } /** * Return whether the name should be rendered. * @param entity Entity * @return True if the name should be rendered, false otherwise */ @Override protected boolean canRenderName(T entity) { return entity.hasCustomName(); } /** * Scale the Model before rendering * @param entitylivingbaseIn Entity to scale * @param partialTickTime Partial Tick Time */ @Override protected void preRenderCallback(T entitylivingbaseIn, float partialTickTime) { GlStateManager.scalef(0.35F, 0.35F, 0.35F); } /** * Apply Rotations to the model * @param entityLiving Entity * @param ageInTicks Age in Ticks * @param rotationYaw Rotation Yaw * @param partialTicks Partial Ticks */ @Override protected void applyRotations(T entityLiving, float ageInTicks, float rotationYaw, float partialTicks) { GlStateManager.translatef(0.0F, MathHelper.cos(ageInTicks * 0.3F) * 0.1F, 0.0F); super.applyRotations(entityLiving, ageInTicks, rotationYaw, partialTicks); } /** * Get the Entity Texture * @param entity Entity * @return Entity Texture */ protected ResourceLocation getEntityTexture(T entity) { return null; } } Any idea on why this happens?
-
Forgot to close the post, i got this to work in the mean time by doing this. Catching the EntityJoinEvent and doing this @SubscribeEvent public static void onBatJoinWorldEvent(final EntityJoinWorldEvent event) { if(event.getEntity() instanceof BatEntity) { BatEntity bat = (BatEntity)event.getEntity(); bat.goalSelector.addGoal(Settings.ATTACK_GOAL_PRIORITY, new AntiBlazeAttackGoal(bat, Settings.ATTACK_GOAL_SPEED, false)); bat.targetSelector.addGoal(Settings.ATTACK_GOAL_PRIORITY, new NearestAttackableTargetGoal<>(bat, AntiBlazeEntity.class, false)); if(bat.getAttributes().getAttributeInstance(SharedMonsterAttributes.ATTACK_DAMAGE) == null) { bat.getAttributes().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE); bat.getAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(Settings.ATTACK_DAMAGE); } } } What i've done is creating a new Goal, wich is essentially the copy of MeleeAttackGoal but with an AmbientEntity instead of a CreatureEntity. Then i've assigned this goal to the goal selector and give the bat a target like you would normally do with an hostile mob (in this case i've set to attack a custom entity from the mod itself, but you can set whatever you want). Then i set the attack damage, but only if the entity doesn't have that attribute already set. This way i managed to turn bats into some nightmares ?
-
Hi everyone! I was trying Forge for 1.14.4 these days and was trying to change to Bat's AI or make an "hostile" version of them. What i tried is to create an entity that extends the Bat Entity and adds the goals and attributes for it to attack players. However i'm clearly missing something since it doesn't work, the entity works fine in the world but is not attacking Here is the entity code (not much) package com.antiblaze.entities; import net.minecraft.entity.EntityType; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.goal.NearestAttackableTargetGoal; import net.minecraft.entity.passive.BatEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.World; /** * @author JimiIT92 */ public class HostileBatEntity extends BatEntity { public HostileBatEntity(EntityType<? extends HostileBatEntity> type, World worldIn) { super(type, worldIn); } @Override protected void registerGoals() { super.registerGoals(); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, PlayerEntity.class, true)); } @Override protected void registerAttributes() { super.registerAttributes(); this.getAttributes().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE); this.getAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(3.0f); } } I've already tried changing this this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, PlayerEntity.class, true)); to this this.goalSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, PlayerEntity.class, true)); but that had no effects. So how can i make this new entity hostile torwards players? Or make the vanilla bats hostile? I know i must subscribe to the EntityJoinWorld event to change their AI's, however i think that giving the bats these goals would have the same "no effect"
-
Make a block only collidable for a specific entity
JimiIT92 replied to MosquitoFRA's topic in Modder Support
I know but he needs to start from somewhere As you can see he still has to learn how to make what he want to do work, i just tell him where to do it, not how -
Make a block only collidable for a specific entity
JimiIT92 replied to MosquitoFRA's topic in Modder Support
What diesieben was trying to say is that you should learn how to check if an entity is of a given instance or has some particular properties defined in the entity class. I'm pretty sure that the entity class itself has no "projectiles" property, and even if it does i don't think it's a boolean by the name. That being said, you should do something like this (assuming you are using Forge 1.12.2) @Override public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entityIn, boolean isActualState) { if(entityIn instanceof EntityPlayer) { // Do stuff } } In this case you check if the entity that collides with the block is a player. If so then you can do whatever you want (like adding the collision box). -
Wheter "using the command" means actually using a command like /something or it means the players does some sort of action (like attacking an entity), you should have an event handler for these events and in that i'm pretty sure you'll find a reference to the player, wich then will give you access to all players informations, like the name in this case. You can find more about how to intercept an event here on the official Forge documentation. Note that this will give you the basics, for more advanced things you have to figure out by your own
-
[1.12.2] Wall blockstates model using forge marker
JimiIT92 replied to JimiIT92's topic in Modder Support
Got it working using this json { "forge_marker": 1, "defaults": { "textures": { "wall": "mineworld:blocks/marble_white" } }, "variants": { "normal": [{ }], "inventory": [{ "model": "wall_inventory" }], "up": { "true": { "model": "wall_post" }, "false": { } }, "north": { "true": { "submodel": { "north": { "model": "wall_side", "uvlock": true } } }, "false": { } }, "south": { "true": { "submodel": { "south": { "model": "wall_side", "uvlock": true, "y": 180 } } }, "false": { } }, "east": { "true": { "submodel": { "east": { "model": "wall_side", "uvlock": true, "y": 90 } } }, "false": { } }, "west": { "true": { "submodel": { "west": { "model": "wall_side", "uvlock": true, "y": 270 } } }, "false": { } } } } So the problem was the false condition as you said but also the fact that i set the model in the defaults section. If i only remove the false condition than the wall won't connect at all, it looks like every piece has a string on top Thank you for your help, i guess i'll try now to use this system with stairs too since is the only kind of block i still use the "old" system EDIT: Just noticed that when i load the game i get this error now But if i define a default model i get the weird thing written above. So how can i avoid this? -
[1.12.2] Wall blockstates model using forge marker
JimiIT92 replied to JimiIT92's topic in Modder Support
Ok now i'm starting to understand how it works, i guess. Infact i changed the json to this, so when there is a long wall connected the middle sections won't have the pillar model { "forge_marker": 1, "defaults": { "textures": { "wall": "mineworld:blocks/marble_white" }, "model": "wall_post" }, "variants": { "normal": [{ }], "inventory": [{ "model": "wall_inventory" }], "up": { "true": { "model": "wall_post" }, "false": { "model": "wall_side" } }, "north": { "true": { "submodel": { "north": { "model": "wall_side", "uvlock": true } } }, "false": { } }, "south": { "true": { "submodel": { "south": { "model": "wall_side", "uvlock": true, "y": 180 } } }, "false": { } }, "east": { "true": { "submodel": { "east": { "model": "wall_side", "uvlock": true, "y": 90 } } }, "false": { } }, "west": { "true": { "submodel": { "west": { "model": "wall_side", "uvlock": true, "y": 270 } } }, "false": { } } } } This works fine except for some cases where the models get mixed up, like in this case -
[1.12.2] Wall blockstates model using forge marker
JimiIT92 replied to JimiIT92's topic in Modder Support
I thought about that but i don't know how to specify "if these conditions happens than use this model". For example, i changed the json file to this { "forge_marker": 1, "defaults": { "textures": { "wall": "mineworld:blocks/marble_white" }, "model": "wall_post" }, "variants": { "normal": [{ }], "inventory": [{ "model": "wall_inventory" }], "up": { "true": { "model": "wall_post" }, "false": { } }, "north": { "true": { "submodel": { "base": { "model": "wall_side", "uvlock": true }, "pillar" : { "model": "wall_post" } } }, "false": { } }, "south": { "true": { "submodel": { "base": { "model": "wall_side", "uvlock": true, "y": 180 }, "pillar" : { "model": "wall_post" } } }, "false": { } }, "east": { "true": { "submodel": { "base": { "model": "wall_side", "uvlock": true, "y": 90 }, "pillar" : { "model": "wall_post" } } }, "false": { } }, "west": { "true": { "submodel": { "base": { "model": "wall_side", "uvlock": true, "y": 270 }, "pillar" : { "model": "wall_post" } } }, "false": { } } } } And now if i connect the wall to 4 blocks (one per side) then only one connection is rendered. Looks like it gets only one model, where i need to tell "if only west or only east is connected use one model, but if both west and east are use another model" -
In forge 1.10.2 i used a json file like this to define the blockstates for my custom wall and everything worked fine (this comes from the vanilla cobblestone wall blockstates file) { "multipart": [ { "when": { "up": "true" }, "apply": { "model": "cobblestone_wall_post" } }, { "when": { "north": "true" }, "apply": { "model": "cobblestone_wall_side", "uvlock": true } }, { "when": { "east": "true" }, "apply": { "model": "cobblestone_wall_side", "y": 90, "uvlock": true } }, { "when": { "south": "true" }, "apply": { "model": "cobblestone_wall_side", "y": 180, "uvlock": true } }, { "when": { "west": "true" }, "apply": { "model": "cobblestone_wall_side", "y": 270, "uvlock": true } } ] } If i change the model defined there to my mod's model everything is fine. But now i'm trying to create the models for my wall using the forge blockstates system because i want to learn more about this system I ended up with this json file, wich is fine unless you connect two walls. { "forge_marker": 1, "defaults": { "textures": { "wall": "mineworld:blocks/marble_white" }, "model": "wall_post" }, "variants": { "normal": [{ }], "inventory": [{ "model": "wall_inventory" }], "up": { "true": { "model": "wall_post" }, "false": { } }, "north": { "true": { "model": "wall_side", "uvlock": true }, "false": { } }, "south": { "true": { "model": "wall_side", "uvlock": true, "y": 180 }, "false": { } }, "east": { "true": { "model": "wall_side", "uvlock": true, "y": 90 }, "false": { } }, "west": { "true": { "model": "wall_side", "uvlock": true, "y": 270 }, "false": { } } } } As you can see this is the result i get when i connect two walls on the side So how can i get it working using the forge system?
-
[SOLVED] [1.12.2] Declaring stairs in the registry event
JimiIT92 replied to JimiIT92's topic in Modder Support
Got it, doing the initialization of the block in a local variable did the trick! Thanks for the help -
As the title said, is it possibile to declare a stair block based on a mod block inside the register event? Right now this is the class i use to declare all my blocks package com.mineworld.core; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import com.mineworld.block.*; import com.mineworld.block.enums.*; import com.mineworld.block.itemblock.*; import com.mineworld.block.slab.*; import com.mineworld.settings.ModSettings; import com.mineworld.utils.BlockUtils; import net.minecraft.block.Block; import net.minecraft.block.BlockSlab; import net.minecraft.block.BlockStairs; import net.minecraft.block.material.MapColor; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemSlab; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.event.RegistryEvent.Register; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder; /** * MineWorld blocks * @author Jimi * */ @EventBusSubscriber @ObjectHolder(ModSettings.MODID) public class MWBlocks { public static final Block RUBY_ORE = null; public static final Block SAPPHIRE_ORE = null; public static final Block COPPER_ORE = null; public static final Block SILVER_ORE = null; public static final Block ALUMINIUM_ORE = null; public static final Block PYRITE_ORE = null; public static final Block RUBY_BLOCK = null; public static final Block SAPPHIRE_BLOCK = null; public static final Block COPPER_BLOCK = null; public static final Block BRONZE_BLOCK = null; public static final Block SILVER_BLOCK = null; public static final Block ALUMINIUM_BLOCK = null; public static final Block PYRITE_BLOCK = null; public static final Block MARBLE = null; public static final BlockHalfOreSlab ORE_SLAB = null; public static final BlockDoubleOreSlab ORE_DOUBLE_SLAB = null; public static final BlockHalfPoweredOreSlab POWERED_ORE_SLAB = null; public static final BlockDoublePoweredOreSlab POWERED_ORE_DOUBLE_SLAB = null; public static final BlockHalfMarbleSlab MARBLE_SLAB = null; public static final BlockDoubleMarbleSlab MARBLE_DOUBLE_SLAB = null; public static final Block RUBY_STAIRS = null; public static final Block SAPPHIRE_STAIRS = null; public static final Block COPPER_STAIRS = null; public static final Block BRONZE_STAIRS = null; public static final Block SILVER_STAIRS = null; public static final Block ALUMINIUM_STAIRS = null; public static final Block WHITE_MARBLE_STAIRS = null; public static final Block BLACK_MARBLE_STAIRS = null; public static final Block RED_MARBLE_STAIRS = null; public static final Block BROWN_MARBLE_STAIRS = null; public static final Block PINK_MARBLE_STAIRS = null; public static final Block YELLOW_MARBLE_STAIRS = null; public static final Block GREEN_MARBLE_STAIRS = null; /** * Register the blocks * @param event Register event */ @SubscribeEvent public static void registerBlocks(Register<Block> event) { event.getRegistry().registerAll( new BlockOreMW("ruby_ore", EnumOre.RUBY.getHarvestLevel()), new BlockOreMW("sapphire_ore", EnumOre.SAPPHIRE.getHarvestLevel()), new BlockOreMW("copper_ore", EnumOre.COPPER.getHarvestLevel()), new BlockOreMW("silver_ore", EnumOre.SILVER.getHarvestLevel()), new BlockOreMW("aluminium_ore", EnumOre.ALUMINIUM.getHarvestLevel()), new BlockOreMW("pyrite_ore", EnumOre.PYRITE.getHarvestLevel()), new BlockCompressedMW("ruby_block", EnumOre.RUBY.getMapColor(), EnumOre.RUBY.getHarvestLevel()), new BlockCompressedMW("sapphire_block", EnumOre.SAPPHIRE.getMapColor(), EnumOre.SAPPHIRE.getHarvestLevel()), new BlockCompressedPoweredMW("copper_block", EnumOre.COPPER.getMapColor(), EnumOre.COPPER.getPowerLevel()), new BlockCompressedPoweredMW("bronze_block", EnumOre.BRONZE.getMapColor(), EnumOre.BRONZE.getPowerLevel()), new BlockCompressedMW("silver_block", EnumOre.SILVER.getMapColor(), EnumOre.SILVER.getHarvestLevel()), new BlockCompressedMW("aluminium_block", EnumOre.ALUMINIUM.getMapColor(), EnumOre.ALUMINIUM.getHarvestLevel()), new BlockCompressedMW("pyrite_block", EnumOre.PYRITE.getMapColor(), EnumOre.PYRITE.getHarvestLevel()), new BlockMarble("marble"), new BlockHalfOreSlab("ore_slab"), new BlockDoubleOreSlab("ore_double_slab"), new BlockHalfPoweredOreSlab("powered_ore_slab"), new BlockDoublePoweredOreSlab("powered_ore_double_slab"), new BlockHalfMarbleSlab("marble_slab"), new BlockDoubleMarbleSlab("marble_double_slab"), new BlockStairsMW("ruby_stairs", Blocks.STONE), new BlockStairsMW("sapphire_stairs", Blocks.STONE), new BlockStairsMW("copper_stairs", Blocks.STONE.getDefaultState(), MWTabs.REDSTONE, EnumOre.COPPER.getPowerLevel()), new BlockStairsMW("bronze_stairs", Blocks.STONE.getDefaultState(), MWTabs.REDSTONE, EnumOre.BRONZE.getPowerLevel()), new BlockStairsMW("silver_stairs", Blocks.STONE), new BlockStairsMW("aluminium_stairs", Blocks.STONE), new BlockStairsMW("white_marble_stairs", Blocks.STONE), new BlockStairsMW("black_marble_stairs", Blocks.STONE), new BlockStairsMW("red_marble_stairs", Blocks.STONE), new BlockStairsMW("brown_marble_stairs", Blocks.STONE), new BlockStairsMW("pink_marble_stairs", Blocks.STONE), new BlockStairsMW("yellow_marble_stairs", Blocks.STONE), new BlockStairsMW("green_marble_stairs", Blocks.STONE) ); } /** * Register the item blocks * @param event Register event */ @SubscribeEvent public static void registerItemBlocks(Register<Item> event) { event.getRegistry().registerAll( new ItemBlock(RUBY_ORE).setRegistryName(RUBY_ORE.getRegistryName()), new ItemBlock(SAPPHIRE_ORE).setRegistryName(SAPPHIRE_ORE.getRegistryName()), new ItemBlock(COPPER_ORE).setRegistryName(COPPER_ORE.getRegistryName()), new ItemBlock(SILVER_ORE).setRegistryName(SILVER_ORE.getRegistryName()), new ItemBlock(ALUMINIUM_ORE).setRegistryName(ALUMINIUM_ORE.getRegistryName()), new ItemBlock(PYRITE_ORE).setRegistryName(PYRITE_ORE.getRegistryName()), new ItemBlock(RUBY_BLOCK).setRegistryName(RUBY_BLOCK.getRegistryName()), new ItemBlock(SAPPHIRE_BLOCK).setRegistryName(SAPPHIRE_BLOCK.getRegistryName()), new ItemBlock(COPPER_BLOCK).setRegistryName(COPPER_BLOCK.getRegistryName()), new ItemBlock(BRONZE_BLOCK).setRegistryName(BRONZE_BLOCK.getRegistryName()), new ItemBlock(SILVER_BLOCK).setRegistryName(SILVER_BLOCK.getRegistryName()), new ItemBlock(ALUMINIUM_BLOCK).setRegistryName(ALUMINIUM_BLOCK.getRegistryName()), new ItemBlock(PYRITE_BLOCK).setRegistryName(PYRITE_BLOCK.getRegistryName()), new ItemBlockVariant(MARBLE, EnumMarble.class).setRegistryName(MARBLE.getRegistryName()), new ItemSlab(ORE_SLAB, ORE_SLAB, ORE_DOUBLE_SLAB).setRegistryName(ORE_SLAB.getRegistryName()), new ItemSlab(POWERED_ORE_SLAB, POWERED_ORE_SLAB, POWERED_ORE_DOUBLE_SLAB).setRegistryName(POWERED_ORE_SLAB.getRegistryName()), new ItemSlab(MARBLE_SLAB, MARBLE_SLAB, MARBLE_DOUBLE_SLAB).setRegistryName(MARBLE_SLAB.getRegistryName()), new ItemBlock(RUBY_STAIRS).setRegistryName(RUBY_STAIRS.getRegistryName()), new ItemBlock(SAPPHIRE_STAIRS).setRegistryName(SAPPHIRE_STAIRS.getRegistryName()), new ItemBlock(COPPER_STAIRS).setRegistryName(COPPER_STAIRS.getRegistryName()), new ItemBlock(BRONZE_STAIRS).setRegistryName(BRONZE_STAIRS.getRegistryName()), new ItemBlock(SILVER_STAIRS).setRegistryName(SILVER_STAIRS.getRegistryName()), new ItemBlock(ALUMINIUM_STAIRS).setRegistryName(ALUMINIUM_STAIRS.getRegistryName()), new ItemBlock(WHITE_MARBLE_STAIRS).setRegistryName(WHITE_MARBLE_STAIRS.getRegistryName()), new ItemBlock(BLACK_MARBLE_STAIRS).setRegistryName(BLACK_MARBLE_STAIRS.getRegistryName()), new ItemBlock(RED_MARBLE_STAIRS).setRegistryName(RED_MARBLE_STAIRS.getRegistryName()), new ItemBlock(BROWN_MARBLE_STAIRS).setRegistryName(BROWN_MARBLE_STAIRS.getRegistryName()), new ItemBlock(PINK_MARBLE_STAIRS).setRegistryName(PINK_MARBLE_STAIRS.getRegistryName()), new ItemBlock(YELLOW_MARBLE_STAIRS).setRegistryName(YELLOW_MARBLE_STAIRS.getRegistryName()), new ItemBlock(GREEN_MARBLE_STAIRS).setRegistryName(GREEN_MARBLE_STAIRS.getRegistryName()) ); } /** * Register the block models * @param event ModelRegistry event */ @SubscribeEvent public static void registerModels(ModelRegistryEvent event) { BlockUtils.registerBlockModel(RUBY_ORE); BlockUtils.registerBlockModel(SAPPHIRE_ORE); BlockUtils.registerBlockModel(COPPER_ORE); BlockUtils.registerBlockModel(SILVER_ORE); BlockUtils.registerBlockModel(ALUMINIUM_ORE); BlockUtils.registerBlockModel(PYRITE_ORE); BlockUtils.registerBlockModel(RUBY_BLOCK); BlockUtils.registerBlockModel(SAPPHIRE_BLOCK); BlockUtils.registerBlockModel(COPPER_BLOCK); BlockUtils.registerBlockModel(BRONZE_BLOCK); BlockUtils.registerBlockModel(SILVER_BLOCK); BlockUtils.registerBlockModel(ALUMINIUM_BLOCK); BlockUtils.registerBlockModel(PYRITE_BLOCK); BlockUtils.registerMetadataBlockModel(MARBLE, "color", EnumMarble.class); BlockUtils.registerSlabBlockModel(ORE_SLAB, "ore", EnumOre.class, true, EnumOre.COPPER, EnumOre.BRONZE, EnumOre.PYRITE); BlockUtils.registerMetadataBlockModel(ORE_DOUBLE_SLAB, "ore", EnumOre.class, true, EnumOre.COPPER, EnumOre.BRONZE, EnumOre.PYRITE); BlockUtils.registerSlabBlockModel(POWERED_ORE_SLAB, "ore", EnumOre.class, false, EnumOre.COPPER, EnumOre.BRONZE); BlockUtils.registerMetadataBlockModel(POWERED_ORE_DOUBLE_SLAB, "ore", EnumOre.class, false, EnumOre.COPPER, EnumOre.BRONZE); BlockUtils.registerSlabBlockModel(MARBLE_SLAB, "color", EnumMarble.class); BlockUtils.registerMetadataBlockModel(MARBLE_DOUBLE_SLAB, "color", EnumMarble.class); BlockUtils.registerBlockModel(RUBY_STAIRS); BlockUtils.registerBlockModel(SAPPHIRE_STAIRS); BlockUtils.registerBlockModel(COPPER_STAIRS); BlockUtils.registerBlockModel(BRONZE_STAIRS); BlockUtils.registerBlockModel(SILVER_STAIRS); BlockUtils.registerBlockModel(ALUMINIUM_STAIRS); BlockUtils.registerBlockModel(WHITE_MARBLE_STAIRS); BlockUtils.registerBlockModel(BLACK_MARBLE_STAIRS); BlockUtils.registerBlockModel(RED_MARBLE_STAIRS); BlockUtils.registerBlockModel(BROWN_MARBLE_STAIRS); BlockUtils.registerBlockModel(PINK_MARBLE_STAIRS); BlockUtils.registerBlockModel(YELLOW_MARBLE_STAIRS); BlockUtils.registerBlockModel(GREEN_MARBLE_STAIRS); } } In the register blocks event i declare my stair using the vanilla stone block as base block. If i change that to RUBY_BLOCK or any other mod blocks the game crashes with a null pointer exception. So how can i use a mod block for the stairs instead of a vanilla one?
-
[SOLVED] [1.12.2] Metadata blocks in inventory
JimiIT92 replied to JimiIT92's topic in Modder Support
Update: so, after spending some time trying to figure out the arcane i did it. Reading the old messages i thought about the "variant=something" thing and i remembered that when you have multiple properties, the blockstate is something like "property1=value1,property2=value2". And so i tried using the "half=bottom,color=white" to register the white slab and it worked! I now have a proper icon displaying in the inventory Thanks everyone for your help