-
Posts
274 -
Joined
-
Days Won
5
Everything posted by imacatlolol
-
[1.114.4] Adding ItemStacks to World
imacatlolol replied to Frost Dragon Empire's topic in Modder Support
Check the class again; you'll want to spawn an item entity on the server-side world, using its provided methods to do so. -
It does, look at ShulkerBoxBlock#addInformation, which itself gets called inside of BlockItem to add the block's tooltips to its item.
-
I'm migrating one of my (very) old projects to the latest version of Forge, and am having to re-learn a handful of things. Smooth sailing so far, but I came across this little road bump: I have a block that is able to copy the model of any other block. To do so, it uses a tile entity that stores the source block's default state (serialized as a resource location string) for rendering. To access the tile entity from the baked model I was using, I would store the tile entity inside of the block state with an IUnlistedProperty, which has since been removed. The primer suggests using extended states for this kind of thing, but that's been a dead end (the primer even says that it's "not working just yet") My general ideas for solutions are the following: Stop using a baked model and switch to a TileEntityRendererFast. This is the most straightforward solution, but I can't figure out how to make this also work for rendering the item. Also I'm not 100% sure on the performance here, since I assume the baked model solution is faster to some degree (but that might be negligible for all I know). Store a resource location (or string) in the block state's properties, to then be retrieved during rendering. This doesn't seem like it would work due to how properties work now (i.e. getAllowedValues), but I might be misinterpreting it entirely. Find some other way to access the tile entity from a baked model's getQuads method? IModelData seems like a lead to follow for that, but I'm not so sure. This feels like an easy solution to look for, but I'm having just a bit of trouble finding it. I just need to copy another block's model and have it also apply to the camo block's item. Edit: Side note, I'm using a tile entity regardless for other reasons, which is why I felt the need to use one in the first place. The second of my above proposed solutions would be an ideal solution if I wasn't using a tile entity, I think.
-
[1.10.2][SOLVED]Exception loading model [model] with loader Variant
imacatlolol replied to Astelot's topic in Modder Support
Yikes! Well I'm afraid I don't know enough to be of much help then I'm sorry -
[1.10.2][SOLVED]Exception loading model [model] with loader Variant
imacatlolol replied to Astelot's topic in Modder Support
Hmm, going off of my own code for when I was having similar issues, try this instead: { "forge_marker": 1, "defaults": { "model": "arpgf:plainTable", "textures": { "0": "blocks/log_oak", "1": "blocks/log_oak_top" } }, "variants": { "oak": { "textures": { "0": "blocks/log_oak", "1": "blocks/log_oak_top" } }, "jungle": { "textures": { "0": "blocks/log_jungle", "1": "blocks/log_jungle_top" } }, "spruce": { "textures": { "0": "blocks/log_spruce", "1": "blocks/log_spruce_top" } }, "acacia": { "textures": { "0": "blocks/log_acacia", "1": "blocks/log_acacia_top" } }, "big_oak": { "textures": { "0": "blocks/log_big_oak", "1": "blocks/log_big_oak_top" } }, "birch": { "textures": { "0": "blocks/log_birch", "1": "blocks/log_birch_top" } } }, "cover": { "true": { "submodel": "arpgf:cover" }, "false": {} } } I removed the extra "varient" so that it goes straight from "varients" to "oak", etc. (I'm somewhat inexperienced with blockstates, though.) -
[1.10.2][SOLVED]Exception loading model [model] with loader Variant
imacatlolol replied to Astelot's topic in Modder Support
You need to add the missing variants into your blockstate. For example, because it says Exception loading model arpgf:BlockPlainTable#variant=spruce you'll need to add "spruce": { "textures": { "0": "blocks/log_spruce", "1": "blocks/log_spruce_top" } } to your blockstate varients. Do this for every other variant that it reports missing (I'm sure there's a way to have it ignore certain variants so you don't have to put them in the blockstate, though I am not sure what that would be.) -
Check out BlockTNT.java and go from there. For making the one that shoots lava everywhere, try having it spawn falling blocks with the block set to lava, and having those blocks spawn just before the explosion to have them actually go everywhere.
-
Well this: protected boolean isEmptyBlock(Block blockIn) { return blockIn.getMaterial(blockIn.getDefaultState()) == Material.AIR || blockIn == Blocks.FIRE || blockIn == Blocks.PORTAL; } is telling it that fire is technically a valid empty block, so I don't think that's it. After a little more looking, I realized that the isValid() checks aren't actually failing, otherwise trySpawnPortal would return false (it's returning true)...
-
EDIT: I must be either blind, dumb, or both. I finally realized that when I was doing the isEmptyBlock check, I was checking the vanilla portal, not my own. I was so sure that I had replaced all of the vanilla portal-related stuff will me own stuff I was completely oblivious to it. I can't believe I wasted so much time on this I'm attempting to create a custom portal to a custom dimension. I have managed to get the portal to generate correctly under normal circumstances, but ever since I tried to get it to generate from fire (like how the nether portal works) it vanishes as soon as it generates. My portal frame: public class BlockPortalFrame extends Block { public BlockPortalFrame() { super(Material.IRON); setRegistryName("block_portal_frame"); setUnlocalizedName("block_portal_frame"); setCreativeTab(CreativeTab.Mod_TAB); setSoundType(SoundType.METAL); setResistance(10.0F); setHardness(5.0F); setLightLevel(0.9F); setHarvestLevel("pickaxe", 2); } @Override public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos neighbor) { if (worldIn.getBlockState(neighbor).getBlock() == Blocks.FIRE) { ModBlocks.BLOCK_PORTAL.trySpawnPortal(worldIn, neighbor); } } } My portal block: public class BlockModPortal extends BlockPortal { public BlockModPortal() { super(); setRegistryName("block_portal"); setUnlocalizedName("block_portal"); setSoundType(SoundType.GLASS); setHardness(-1.0F); setLightLevel(0.75F); } @Override @SideOnly(Side.CLIENT) public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { if (rand.nextInt(100) == 0) { worldIn.playSound((double)pos.getX() + 0.5D, (double)pos.getY() + 0.5D, (double)pos.getZ() + 0.5D, SoundEvents.BLOCK_PORTAL_AMBIENT, SoundCategory.BLOCKS, 0.5F, rand.nextFloat() * 0.4F + 0.8F, false); } for (int i = 0; i < 4; ++i) { double d0 = (double)((float)pos.getX() + rand.nextFloat()); double d1 = (double)((float)pos.getY() + rand.nextFloat()); double d2 = (double)((float)pos.getZ() + rand.nextFloat()); double d3 = ((double)rand.nextFloat() - 0.5D) * 0.5D; double d4 = ((double)rand.nextFloat() - 0.5D) * 0.5D; double d5 = ((double)rand.nextFloat() - 0.5D) * 0.5D; int j = rand.nextInt(2) * 2 - 1; if (worldIn.getBlockState(pos.west()).getBlock() != this && worldIn.getBlockState(pos.east()).getBlock() != this) { d0 = (double)pos.getX() + 0.5D + 0.25D * (double)j; d3 = (double)(rand.nextFloat() * 2.0F * (float)j); } else { d2 = (double)pos.getZ() + 0.5D + 0.25D * (double)j; d5 = (double)(rand.nextFloat() * 2.0F * (float)j); } worldIn.spawnParticle(EnumParticleTypes.PORTAL, d0, d1, d2, d3, d4, d5, new int[0]); } } @Override public boolean trySpawnPortal(World worldIn, BlockPos pos) { BlockModPortal.Size blockmodportal$size = new BlockModPortal.Size(worldIn, pos, EnumFacing.Axis.X); if (blockmodportal$size.isValid() && blockmodportal$size.portalBlockCount == 0) { blockmodportal$size.placePortalBlocks(); return true; } else { BlockModPortal.Size blockmodportal$size1 = new BlockModPortal.Size(worldIn, pos, EnumFacing.Axis.Z); if (blockmodportal$size1.isValid() && blockmodportal$size1.portalBlockCount == 0) { blockmodportal$size1.placePortalBlocks(); return true; } else { return false; } } } @Override public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos neighbor) { EnumFacing.Axis enumfacing$axis = (EnumFacing.Axis)state.getValue(AXIS); if (enumfacing$axis == EnumFacing.Axis.X) { BlockModPortal.Size blockmodportal$size = new BlockModPortal.Size(worldIn, pos, EnumFacing.Axis.X); if (!blockmodportal$size.isValid() || blockmodportal$size.portalBlockCount < blockmodportal$size.width * blockmodportal$size.height) { worldIn.setBlockState(pos, Blocks.AIR.getDefaultState()); } } else if (enumfacing$axis == EnumFacing.Axis.Z) { BlockModPortal.Size blockmodportal$size1 = new BlockModPortal.Size(worldIn, pos, EnumFacing.Axis.Z); if (!blockmodportal$size1.isValid() || blockmodportal$size1.portalBlockCount < blockmodportal$size1.width * blockmodportal$size1.height) { worldIn.setBlockState(pos, Blocks.AIR.getDefaultState()); } } } @Override public BlockPattern.PatternHelper createPatternHelper(World worldIn, BlockPos blockPos) { EnumFacing.Axis enumfacing$axis = EnumFacing.Axis.Z; BlockModPortal.Size blockmodportal$size = new BlockModPortal.Size(worldIn, blockPos, EnumFacing.Axis.X); LoadingCache<BlockPos, BlockWorldState> loadingcache = BlockPattern.createLoadingCache(worldIn, true); if (!blockmodportal$size.isValid()) { enumfacing$axis = EnumFacing.Axis.X; blockmodportal$size = new BlockModPortal.Size(worldIn, blockPos, EnumFacing.Axis.Z); } if (!blockmodportal$size.isValid()) { return new BlockPattern.PatternHelper(blockPos, EnumFacing.NORTH, EnumFacing.UP, loadingcache, 1, 1, 1); } else { int[] aint = new int[EnumFacing.AxisDirection.values().length]; EnumFacing enumfacing = blockmodportal$size.rightDir.rotateYCCW(); BlockPos blockpos = blockmodportal$size.bottomLeft.up(blockmodportal$size.getHeight() - 1); for (EnumFacing.AxisDirection enumfacing$axisdirection : EnumFacing.AxisDirection.values()) { BlockPattern.PatternHelper blockpattern$patternhelper = new BlockPattern.PatternHelper(enumfacing.getAxisDirection() == enumfacing$axisdirection ? blockpos : blockpos.offset(blockmodportal$size.rightDir, blockmodportal$size.getWidth() - 1), EnumFacing.getFacingFromAxis(enumfacing$axisdirection, enumfacing$axis), EnumFacing.UP, loadingcache, blockmodportal$size.getWidth(), blockmodportal$size.getHeight(), 1); for (int i = 0; i < blockmodportal$size.getWidth(); ++i) { for (int j = 0; j < blockmodportal$size.getHeight(); ++j) { BlockWorldState blockworldstate = blockpattern$patternhelper.translateOffset(i, j, 1); if (blockworldstate.getBlockState().getMaterial() != Material.AIR) { ++aint[enumfacing$axisdirection.ordinal()]; } } } } EnumFacing.AxisDirection enumfacing$axisdirection1 = EnumFacing.AxisDirection.POSITIVE; for (EnumFacing.AxisDirection enumfacing$axisdirection2 : EnumFacing.AxisDirection.values()) { if (aint[enumfacing$axisdirection2.ordinal()] < aint[enumfacing$axisdirection1.ordinal()]) { enumfacing$axisdirection1 = enumfacing$axisdirection2; } } return new BlockPattern.PatternHelper(enumfacing.getAxisDirection() == enumfacing$axisdirection1 ? blockpos : blockpos.offset(blockmodportal$size.rightDir, blockmodportal$size.getWidth() - 1), EnumFacing.getFacingFromAxis(enumfacing$axisdirection1, enumfacing$axis), EnumFacing.UP, loadingcache, blockmodportal$size.getWidth(), blockmodportal$size.getHeight(), 1); } } public static class Size { private final World world; private final EnumFacing.Axis axis; private final EnumFacing rightDir; private final EnumFacing leftDir; private int portalBlockCount; private BlockPos bottomLeft; private int height; private int width; public Size(World worldIn, BlockPos blockPos, EnumFacing.Axis axis) { this.world = worldIn; this.axis = axis; if (axis == EnumFacing.Axis.X) { this.leftDir = EnumFacing.EAST; this.rightDir = EnumFacing.WEST; } else { this.leftDir = EnumFacing.NORTH; this.rightDir = EnumFacing.SOUTH; } for (BlockPos blockpos = blockPos; blockPos.getY() > blockpos.getY() - 21 && blockPos.getY() > 0 && this.isEmptyBlock(worldIn.getBlockState(blockPos.down()).getBlock()); blockPos = blockPos.down()) { ; } int i = this.getDistanceUntilEdge(blockPos, this.leftDir) - 1; if (i >= 0) { this.bottomLeft = blockPos.offset(this.leftDir, i); this.width = this.getDistanceUntilEdge(this.bottomLeft, this.rightDir); if (this.width < 2 || this.width > 21) { this.bottomLeft = null; this.width = 0; } } if (this.bottomLeft != null) { this.height = this.calculatePortalHeight(); } } protected int getDistanceUntilEdge(BlockPos blockPos, EnumFacing enumFacing) { int i; for (i = 0; i < 22; ++i) { BlockPos blockpos = blockPos.offset(enumFacing, i); if (!this.isEmptyBlock(this.world.getBlockState(blockpos).getBlock()) || this.world.getBlockState(blockpos.down()).getBlock() != ModBlocks.BLOCK_PORTAL_FRAME) { break; } } Block block = this.world.getBlockState(blockPos.offset(enumFacing, i)).getBlock(); return block == ModBlocks.BLOCK_PORTAL_FRAME ? i : 0; } public int getHeight() { return this.height; } public int getWidth() { return this.width; } protected int calculatePortalHeight() { label24: for (this.height = 0; this.height < 21; ++this.height) { for (int i = 0; i < this.width; ++i) { BlockPos blockpos = this.bottomLeft.offset(this.rightDir, i).up(this.height); Block block = this.world.getBlockState(blockpos).getBlock(); if (!this.isEmptyBlock(block)) { break label24; } if (block == ModBlocks.BLOCK_PORTAL) { ++this.portalBlockCount; } if (i == 0) { block = this.world.getBlockState(blockpos.offset(this.leftDir)).getBlock(); if (block != ModBlocks.BLOCK_PORTAL_FRAME) { break label24; } } else if (i == this.width - 1) { block = this.world.getBlockState(blockpos.offset(this.rightDir)).getBlock(); if (block != ModBlocks.BLOCK_PORTAL_FRAME) { break label24; } } } } for (int j = 0; j < this.width; ++j) { if (this.world.getBlockState(this.bottomLeft.offset(this.rightDir, j).up(this.height)).getBlock() != ModBlocks.BLOCK_PORTAL_FRAME) { this.height = 0; break; } } if (this.height <= 21 && this.height >= 3) { return this.height; } else { this.bottomLeft = null; this.width = 0; this.height = 0; return 0; } } protected boolean isEmptyBlock(Block blockIn) { return blockIn.getMaterial(blockIn.getDefaultState()) == Material.AIR || blockIn == Blocks.FIRE || blockIn == Blocks.PORTAL; } public boolean isValid() { return this.bottomLeft != null && this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21; } public void placePortalBlocks() { for (int i = 0; i < this.width; ++i) { BlockPos blockpos = this.bottomLeft.offset(this.rightDir, i); for (int j = 0; j < this.height; ++j) { this.world.setBlockState(blockpos.up(j), ModBlocks.BLOCK_PORTAL.getDefaultState().withProperty(BlockModPortal.AXIS, this.axis), 2); } } } } } Through debugging, I noticed that it does, in fact, generate. It just disappears instantly, at least partly because of neighborChanged failing the isValid() check(s). For some reason, isValid() is returning false because bottomLeft is returning null and both the width and height are returning 0. I've been staring at this for so long my brain is turning into jello, so I was hoping someone with a fresher (and probably better) mind could help me!
-
Custom Crop Crashes w/ Unknown Error Upon Planting.
imacatlolol replied to gmod622's topic in Modder Support
Make sure you're registering your crop block and seed item at the exact same time (as in, put their registration in the same file. I use a separate class for items and blocks that need to be registered together). -
I'm having issues getting some of my models to work. I've decided that the best thing I can do is change how I register models. At the moment, I use something like this and I load it in the initialization phase: public static void registerRender(Item item) { Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory")); } public static void registerRender(Block block) { Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory")); } What would be a better alternative?
-
[SOLVED][1.8.9] Crop not dropping seeds?
imacatlolol replied to imacatlolol's topic in Modder Support
Ah, that was certainly part of the problem, thank you. I was registering my items before my blocks, for whatever reason. But, I've got a problem with the second half. I want to use one class for all of my crops, instead of making a new class for each one (mostly as an experiment to see if it's a good idea). That means I need to be able to set the seed drop and crop drop when I'm registering the crop block. There's probably an easy way to do it and I'm just being blind, but if not I'll go back to making individual classes. Got it. I was thinking it would be useful in some way, but it's not really necessary. -
Hi there! I'm pretty inexperienced with modding and Java in general, so I apologize if this is an easy fix. I'm trying to make a custom crop, but it won't drop the seeds. Instead, I get the following error: "Attempted to add a EntityItem to the world with a invalid item at (-77.33, 4.57, 1181.27), this is most likely a config issue between you and the server. Please double check your configs" ItemPPSeed: public class ItemPPSeed extends ItemSeeds { public ItemPPSeed(String unlocalizedName, int maxStackSize, Block crops, Block soil) { super(crops, soil); this.setCreativeTab(CreativeTabPP.PP_TAB); this.setMaxStackSize(maxStackSize); this.setUnlocalizedName(unlocalizedName); } @Override public String getUnlocalizedName() { return String.format("item.%s%s", RefStr.MOD_ID.toLowerCase() + ":", getUnwrappedUnlocalizedName(super.getUnlocalizedName())); } @Override public String getUnlocalizedName(ItemStack itemStack) { return String.format("item.%s%s", RefStr.MOD_ID.toLowerCase() + ":", getUnwrappedUnlocalizedName(super.getUnlocalizedName())); } protected String getUnwrappedUnlocalizedName(String unlocalizedName) { return unlocalizedName.substring(unlocalizedName.indexOf(".") + 1); } } BlockPPCrop: public class BlockPPCrop extends BlockCrops { private Item seed; private Item crop; public BlockPPCrop(String unlocalizedName, Item seed, Item crop) { this.setDefaultState(this.blockState.getBaseState().withProperty(AGE, 0)); this.setTickRandomly(true); float f = 0.5F; this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.25F, 0.5F + f); this.setCreativeTab(null); this.setHardness(0.0F); this.setStepSound(soundTypeGrass); this.disableStats(); this.setUnlocalizedName(unlocalizedName); this.seed = seed; this.crop = crop; } @Override protected Item getSeed() { return this.seed; } @Override protected Item getCrop() { return this.crop; } @Override public String getUnlocalizedName() { return String.format("tile.%s%s", RefStr.MOD_ID.toLowerCase() + ":", getUnwrappedUnlocalizedName(super.getUnlocalizedName())); } protected String getUnwrappedUnlocalizedName(String unlocalizedName) { return unlocalizedName.substring(unlocalizedName.indexOf(".") + 1); } } Relevant ModItems Line: public static final ItemPPSeed tomatoseed = new ItemPPSeed("tomatoseed", 64, ModBlocks.tomatocrop, Blocks.farmland); Relevant ModBlocks Line: public static final BlockPPCrop tomatocrop = new BlockPPCrop("tomatocrop", ModItems.tomatoseed, ModItems.tomato); The confusing thing is that it drops the tomato fine, but not the seeds.
-
[1.7.10][SOLVED] Custom "Potions" (NOT Potion Effects)
imacatlolol replied to imacatlolol's topic in Modder Support
Thanks! I don't think I'll use it specifically (I'm trying to learn how to write this kind of complex thing on my own, instead of copying everything I come across), but this certainly gives me an idea of I do need to do! Thanks again! -
Hi! I'm back with another question! I'm trying to my own "potion" system, which adds empty glasses and filled glasses (of many different shapes and sizes). I've already made my many empty glass textures and my color-able overlay textures, but I can't figure out how to put this together. If I try and do "ItemGlassBottle" like what the normal bottle does, it replaces my textures with its own and it gets replaced with a water bottle if used on water. I could perhaps try and make a food item instead, but then I'd get the chewing sound effect instead of the drinking one, and the glass would vanish (I want it to return empty, like normal potions). Also, I don't know how I would apply a color-able overlay to a food item (in a similar way to the official potions, I assume, but I'm not sure). This is all very confusing, so if someone could shoot me an easy workaround (if possible), it would be much appreciated!
-
[1.7.10][SOLVED] Block Texture Controlled By Sides & Metadata
imacatlolol replied to imacatlolol's topic in Modder Support
I got it mixed up with where you're actually supposed to put them, lol. If anything, such a mistake isn't likely to happen again! -
[1.7.10][SOLVED] Block Texture Controlled By Sides & Metadata
imacatlolol replied to imacatlolol's topic in Modder Support
Thanks, works great! As it happens, I put the textures in the bin directory, so it seems I'm going to have to make all 12 textures again (I really should have backed them up before I cleaned it). -
Hello! First of all, I'm brand spanking new to Minecraft modding, so my apologies if I ask too many questions! I'm attempting to make a block that has two textures (texture #1 is on the top and bottom, texture #2 is on all four other sides). I want these textures to be controlled by what metadata the block has, as well as which side said texture should be applied to. How would I do this? (I will provide what I've already got if need-be).