kramlat Posted February 25, 2016 Posted February 25, 2016 I am planning a very unique mod, called Customcraft (allows you to create custom blocks, biomes, items, entities, etc from inside minecraft while loaded by commands, textures and locale would use a resource pack to apply if the names are totally custom) and I have a question. What is the max number within reason that one could have of blocks, items, biomes, entities, and dimensions loaded by a mod without a crash? This will help with construction of an array to avoid pointers. Quote
Draco18s Posted February 25, 2016 Posted February 25, 2016 4096 is the limit on blocks, from vanilla plus all loaded mods. I think the item limit is 32,000ish. Biomes are limited to 255, IIRC. Mobs are limited to 255 per mod. Dimensions are effectively unlimited (Mystcraft and RF Tools both allow players to create dimensions). The dimension ID is a signed integer. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
kramlat Posted February 25, 2016 Author Posted February 25, 2016 thanks, that is exactly what I asked for. I guess it is time to make the array structures (will declare static final so that preinit() can do the work of defining all that stuff and load() can do the saved registrations, and also I can use an index to push new blocks into the array and register them at runtime. Mobs are limited to 255 per mod. Not true. Mod entities can use the complete integer range. char, short, or long? Quote
Draco18s Posted February 26, 2016 Posted February 26, 2016 Not true. Mod entities can use the complete integer range. Huh. Never looked into it, I guess. char, short, or long? Integer, which is 32 bits. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
Elix_x Posted February 26, 2016 Posted February 26, 2016 Block ids are from 256 (below is minecraft) to 4096, so 3840 in total. Item ids are from 4096 to 32767, so 28671 in total. Side note: some of these limits can be raised, but require hell lot of bytecode manipultions and frequently cause severe compatibility problems. Quote Check out my mods: BTAM Armor sets Avoid Exploding Creepers Tools compressor Anti Id Conflict Key bindings overhaul Colourfull blocks Invisi Zones
kramlat Posted February 27, 2016 Author Posted February 27, 2016 okay, next question: how do you write to a config file outside of preinit()? the "create block" command needs to know how to do this. Do I need to override the Configuration class? I am able to get values, but I need to be able to set them. Quote
Draco18s Posted February 27, 2016 Posted February 27, 2016 Save the config to a static variable in your main class. Access it from anywhere. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
kramlat Posted February 27, 2016 Author Posted February 27, 2016 Save the config to a static variable in your main class. Access it from anywhere. Already did that, just how do you write to it. There is an overloaded get() function, but not an overloaded set() method. I also indexed all of Materials and SoundTypes with ints the main class. by indexed with ints I mean I used an int value and a switch / case structure that assigns existing Materials and SoundTypes to variables that we used to build the block to be registered. main class: package org.CyberneticStudios.CustomBlocks; import java.io.File; import org.CyberneticStudios.CustomBlocks.Block.BlockCustom; import org.CyberneticStudios.CustomBlocks.common.CommonProxy; import net.minecraft.block.Block; import net.minecraft.block.Block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @Mod(modid=CustomBlocks.MODID, name=CustomBlocks.MODNAME, version=CustomBlocks.MODVER) //Tell forge "Oh hey, there's a new mod here to load." public class CustomBlocks //Start the class Declaration { //Set the ID of the mod (Should be lower case). public static final String MODID = "customBlocks"; //Set the "Name" of the mod. public static final String MODNAME = "Custom Blocks"; //Set the version of the mod. public static final String MODVER = "0.0.0"; @Instance(value = CustomBlocks.MODID) //Tell Forge what instance to use. public static CustomBlocks instance; @SidedProxy(clientSide="org.CyberneticStudios.CustomBlocks.client.ClientProxy", serverSide="org.CyberneticStudios.CustomBlocks.common.CommonProxy") public static CommonProxy proxy; //Used for creative tab public final static Block customBlock = new BlockCustom(Material.ground) .setHardness(0.5F).setStepSound(Block.soundTypeGravel) .setUnlocalizedName("custom_block"); public static final CreativeTabs customBlocks= new CreativeTabs("custom_blocks") { @Override @SideOnly(Side.CLIENT) public Item getTabIconItem(){ ItemStack iStack = new ItemStack(customBlock); return iStack.getItem(); } }; //empty stack of allocated blocks public static Block[] emptyBlocks = new Block[3839]; //now we need an index public static int blockIndex; //set up configuration public static File configFile; public static Configuration config; @EventHandler public void preInit(FMLPreInitializationEvent event) { // you will be able to find the config file in .minecraft/config/ and it will be named Dummy.cfg // here our Configuration has been instantiated, and saved under the name "config" configFile = event.getSuggestedConfigurationFile(); config = new Configuration(event.getSuggestedConfigurationFile()); // loading the configuration from its file config.load(); blockIndex = config.getInt("BlockCount", "B", 0, 0, 3839, "The number of custom blocks"); int currentIndex = 0; while (currentIndex < blockIndex){ Material blkMaterial; switch (config.getInt("Material", "B:Block" + Integer.toString(currentIndex), 0, 0, 34, "The current block's material.")) { case 0: blkMaterial = Material.air; break; case 1: blkMaterial = Material.grass; break; case 2: blkMaterial = Material.ground; break; case 3: blkMaterial = Material.wood; break; case 4: blkMaterial = Material.rock; break; case 5: blkMaterial = Material.iron; break; case 6: blkMaterial = Material.anvil; break; case 7: blkMaterial = Material.water; break; case 8: blkMaterial = Material.lava; break; case 9: blkMaterial = Material.leaves; break; case 10: blkMaterial = Material.plants; break; case 11: blkMaterial = Material.vine; break; case 12: blkMaterial = Material.sponge; break; case 13: blkMaterial = Material.cloth; break; case 14: blkMaterial = Material.fire; break; case 15: blkMaterial = Material.sand; break; case 16: blkMaterial = Material.circuits; break; case 17: blkMaterial = Material.carpet; break; case 18: blkMaterial = Material.glass; break; case 19: blkMaterial = Material.redstoneLight; break; case 20: blkMaterial = Material.tnt; break; case 21: blkMaterial = Material.coral; break; case 22: blkMaterial = Material.ice; break; case 23: blkMaterial = Material.packedIce; break; case 24: blkMaterial = Material.snow; break; case 25: blkMaterial = Material.craftedSnow; break; case 26: blkMaterial = Material.cactus; break; case 27: blkMaterial = Material.clay; break; case 28: blkMaterial = Material.gourd; break; case 29: blkMaterial = Material.dragonEgg; break; case 30: blkMaterial = Material.portal; break; case 31: blkMaterial = Material.cake; break; case 32: blkMaterial = Material.web; break; case 33: blkMaterial = Material.piston; break; case 34: blkMaterial = Material.barrier; break; default: blkMaterial = Material.air; } float hardness = config.getFloat("Hardness", "B:Block" + Integer.toString(currentIndex), 0.5F, 3.4e-038F, 3.4e+038F, "Sets how many hits it takes to break a block."); SoundType stepSound; switch(config.getInt("StepSound", "B:Block" + Integer.toString(currentIndex), 0, 0, 12, "the sound that plays when walking on our block")) { case 0: stepSound = Block.soundTypeStone; break; case 1: stepSound = Block.soundTypeWood; break; case 2: stepSound = Block.soundTypeGravel; break; case 3: stepSound = Block.soundTypeGrass; break; case 4: stepSound = Block.soundTypePiston; break; case 5: stepSound = Block.soundTypeMetal; break; case 6: stepSound = Block.soundTypeGlass; break; case 7: stepSound = Block.soundTypeCloth; break; case 8: stepSound = Block.soundTypeSand; break; case 9: stepSound = Block.soundTypeSnow; break; case 10: stepSound = Block.soundTypeLadder; break; case 11: stepSound = Block.soundTypeAnvil; break; case 12: stepSound = Block.SLIME_SOUND; break; default: stepSound = Block.soundTypeStone; } int lightOpacity = config.getInt("LightOpacity", "B:Block" + Integer.toString(currentIndex), 0, -2147483647, 2147483647, "Sets how much light is blocked going through this block."); float lightLevel = config.getFloat("LightLevel", "B:Block" + Integer.toString(currentIndex), 1.0F, 3.4e-038F, 3.4e+038F, "Sets the light value that the block emits."); float resistance = config.getFloat("Resistance", "B:Block" + Integer.toString(currentIndex), 1.0F, 3.4e-038F, 3.4e+038F, "Sets the the blocks resistance to explosions."); String unlocalizedName = config.getString("UnlocalizedName", "B:Block" + Integer.toString(currentIndex), "generic_block", "the name of the block"); boolean tickRandomly=config.getBoolean("TickRandomly", "B:Block" + Integer.toString(currentIndex), false, "Sets whether this block type will receive random update ticks"); boolean unbreakable=config.getBoolean("Unbreakable", "B:Block" + Integer.toString(currentIndex), false, "Sets whether this block type will receive random update ticks"); if (unbreakable == true){ emptyBlocks[currentIndex] = new BlockCustom(blkMaterial) .setHardness(hardness) .setStepSound(stepSound) .setUnlocalizedName(unlocalizedName) .setLightOpacity(lightOpacity) .setLightLevel(lightLevel) .setResistance(resistance) .setTickRandomly(tickRandomly) .setBlockUnbreakable() .setCreativeTab(customBlocks); }else{ emptyBlocks[currentIndex] = new BlockCustom(blkMaterial) .setHardness(hardness) .setStepSound(stepSound) .setUnlocalizedName(unlocalizedName) .setLightOpacity(lightOpacity) .setLightLevel(lightLevel) .setResistance(resistance) .setTickRandomly(tickRandomly) .setCreativeTab(customBlocks); } currentIndex++; } // saving the configuration to its file config.save(); } @EventHandler public void load(FMLInitializationEvent event) { //register a generic custom block icon for the mod's creative tab GameRegistry.registerBlock(customBlock, "custom_block"); int currentIndex = 0; while (currentIndex < blockIndex){ GameRegistry.registerBlock(emptyBlocks[currentIndex], emptyBlocks[currentIndex].getUnlocalizedName()); Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(Item.getItemFromBlock(emptyBlocks[currentIndex]), 0, new ModelResourceLocation("custom:" + emptyBlocks[currentIndex].getUnlocalizedName(), "inventory")); currentIndex++; } } @EventHandler public void postInit(FMLPostInitializationEvent event) { } } command class: package org.CyberneticStudios.CustomBlocks.Commands; import java.util.ArrayList; import java.util.List; import org.CyberneticStudios.CustomBlocks.CustomBlocks; import org.CyberneticStudios.CustomBlocks.Block.BlockCustom; import net.minecraft.block.Block; import net.minecraft.block.Block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.command.CommandException; import net.minecraft.command.ICommand; import net.minecraft.command.ICommandSender; import net.minecraft.util.BlockPos; import net.minecraft.util.ChatComponentText; import net.minecraftforge.fml.common.registry.GameRegistry; public class CommandCreateBlock implements ICommand { private final List aliases; public CommandCreateBlock() { aliases = new ArrayList(); aliases.add("cb"); aliases.add("mkblock"); } @Override public int compareTo(ICommand arg0) { return 0; } @Override public String getCommandName() { return "create block"; } @Override public String getCommandUsage(ICommandSender sender) { return "create block <block_name> <material> <step sound> <hardness> <light opacity> <light level> <resistance> <needs random ticks?> <unbreakable>"; } @Override public List<String> getCommandAliases() { return aliases; } @Override public void processCommand(ICommandSender sender, String[] args) throws CommandException { if (CustomBlocks.blockIndex < 3840){ String name = args[0]; int material = Integer.valueOf(args[1]); int stepSound = Integer.valueOf(args[2]); float hardness = Float.valueOf(args[3]); int lightOpacity = Integer.valueOf(args[4]); float lightLevel = Float.valueOf(args[5]); float resistance = Float.valueOf(args[6]); boolean tickRandomly=Boolean.valueOf(args[7]); boolean unbreakable=Boolean.valueOf(args[8]); Material blkMaterial; SoundType stepSound_; if (CustomBlocks.blockIndex < 3839) CustomBlocks.blockIndex++; switch (material) { case 0: blkMaterial = Material.air; break; case 1: blkMaterial = Material.grass; break; case 2: blkMaterial = Material.ground; break; case 3: blkMaterial = Material.wood; break; case 4: blkMaterial = Material.rock; break; case 5: blkMaterial = Material.iron; break; case 6: blkMaterial = Material.anvil; break; case 7: blkMaterial = Material.water; break; case 8: blkMaterial = Material.lava; break; case 9: blkMaterial = Material.leaves; break; case 10: blkMaterial = Material.plants; break; case 11: blkMaterial = Material.vine; break; case 12: blkMaterial = Material.sponge; break; case 13: blkMaterial = Material.cloth; break; case 14: blkMaterial = Material.fire; break; case 15: blkMaterial = Material.sand; break; case 16: blkMaterial = Material.circuits; break; case 17: blkMaterial = Material.carpet; break; case 18: blkMaterial = Material.glass; break; case 19: blkMaterial = Material.redstoneLight; break; case 20: blkMaterial = Material.tnt; break; case 21: blkMaterial = Material.coral; break; case 22: blkMaterial = Material.ice; break; case 23: blkMaterial = Material.packedIce; break; case 24: blkMaterial = Material.snow; break; case 25: blkMaterial = Material.craftedSnow; break; case 26: blkMaterial = Material.cactus; break; case 27: blkMaterial = Material.clay; break; case 28: blkMaterial = Material.gourd; break; case 29: blkMaterial = Material.dragonEgg; break; case 30: blkMaterial = Material.portal; break; case 31: blkMaterial = Material.cake; break; case 32: blkMaterial = Material.web; break; case 33: blkMaterial = Material.piston; break; case 34: blkMaterial = Material.barrier; break; default: blkMaterial = Material.air; } switch(stepSound) { case 0: stepSound_ = Block.soundTypeStone; break; case 1: stepSound_ = Block.soundTypeWood; break; case 2: stepSound_ = Block.soundTypeGravel; break; case 3: stepSound_ = Block.soundTypeGrass; break; case 4: stepSound_ = Block.soundTypePiston; break; case 5: stepSound_ = Block.soundTypeMetal; break; case 6: stepSound_ = Block.soundTypeGlass; break; case 7: stepSound_ = Block.soundTypeCloth; break; case 8: stepSound_ = Block.soundTypeSand; break; case 9: stepSound_ = Block.soundTypeSnow; break; case 10: stepSound_ = Block.soundTypeLadder; break; case 11: stepSound_ = Block.soundTypeAnvil; break; case 12: stepSound_ = Block.SLIME_SOUND; break; default: stepSound_ = Block.soundTypeStone; } if(unbreakable == true){ CustomBlocks.emptyBlocks[CustomBlocks.blockIndex] = new BlockCustom(blkMaterial) .setHardness(hardness) .setStepSound(stepSound_) .setUnlocalizedName(name) .setLightOpacity(lightOpacity) .setLightLevel(lightLevel) .setResistance(resistance) .setTickRandomly(tickRandomly) .setBlockUnbreakable() .setCreativeTab(CustomBlocks.customBlocks); }else{ CustomBlocks.emptyBlocks[CustomBlocks.blockIndex] = new BlockCustom(blkMaterial) .setHardness(hardness) .setStepSound(stepSound_) .setUnlocalizedName(name) .setLightOpacity(lightOpacity) .setLightLevel(lightLevel) .setResistance(resistance) .setTickRandomly(tickRandomly) .setCreativeTab(CustomBlocks.customBlocks); } GameRegistry.registerBlock(CustomBlocks.emptyBlocks[CustomBlocks.blockIndex], CustomBlocks.emptyBlocks[CustomBlocks.blockIndex].getUnlocalizedName()); sender.addChatMessage(new ChatComponentText("Created new custom block: custom:" + name)); // what do I put here to write the config settings? CustomBlocks.config.save(); } else sender.addChatMessage(new ChatComponentText("Too many custom blocks exist in the game.")); } @Override public boolean canCommandSenderUseCommand(ICommandSender sender) { return true; } @Override public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { return null; } @Override public boolean isUsernameIndex(String[] args, int index) { return false; } } I know that the code isn't perfect, this is what I came up with in a short time and thus very messy. I have yet to merge some of the preinit and init code together as well as move to a custom SoundTypes and custom materials model, the custom block class needs more code so that the new blocks can be tweaked as well, but that will be done while I wait. Quote
kramlat Posted February 27, 2016 Author Posted February 27, 2016 There are versions of the get method that return a Property. Property has a set method. but will that allow live config edits? Quote
kramlat Posted February 27, 2016 Author Posted February 27, 2016 I know this might sound very dumb, but I have yet to find a single tutorial on how to use that version of get on the wiki or youtube, mind explaining how to use that get() with an example? Quote
kramlat Posted February 28, 2016 Author Posted February 28, 2016 yes, and I had no idea that even existed, thanks, that is exactly what I was looking for. Quote
kramlat Posted February 28, 2016 Author Posted February 28, 2016 Here is what I ended up using: Property p = CustomBlocks.config.get("B", "BlockCount", "0", "The number of custom blocks") .setValue(CustomBlocks.blockIndex); p = CustomBlocks.config.get("Material", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "0", "The current block's material.") .setValue(material); p = CustomBlocks.config.get("Hardness", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "0.5F", "Sets how many hits it takes to break a block.") .setValue(hardness); p = CustomBlocks.config.get("StepSound", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "0", "the sound that plays when walking on our block") .setValue(stepSound); p = CustomBlocks.config.get("LightOpacity", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "0", "Sets how much light is blocked going through this block.") .setValue(lightOpacity); p = CustomBlocks.config.get("LightLevel", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "1.0F", "Sets the light value that the block emits.") .setValue(lightLevel); p = CustomBlocks.config.get("Resistance", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "1.0F", "Sets the the blocks resistance to explosions.") .setValue(resistance); p = CustomBlocks.config.get("UnlocalizedName", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "generic_block", "the name of the block") .setValue(name); p = CustomBlocks.config.get("TickRandomly", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "false", "Sets whether this block type will receive random update ticks") .setValue(tickRandomly); p = CustomBlocks.config.get("Unbreakable", "B:Block" + Integer.toString(CustomBlocks.blockIndex), "false", "The block can't be broken.") .setValue(unbreakable); [/Code] Quote
Elix_x Posted February 28, 2016 Posted February 28, 2016 Advice: if you want to add blocks dinamically, from configuration, use json and GSON. It will be a lot simpler once you will get hang of them, for both you and users. Quote Check out my mods: BTAM Armor sets Avoid Exploding Creepers Tools compressor Anti Id Conflict Key bindings overhaul Colourfull blocks Invisi Zones
kramlat Posted February 28, 2016 Author Posted February 28, 2016 I could do that in a future release, but what would you recommend for scripting events via resource pack that forge already has? or are my only options invent something, use a lua module that is in an external jar, or another language jar? Also the word is dynamically and I intend to do more than one mod in a jar. I will do the same with materials and Block.SoundTypes next, then items, then biomes, then entities(yes I mean mobs), then dimensions. The jar won't be called Customcraft for nothing. Besides, the end user will be able to add new blocks, items, etc, from console commands. If you read the dated code above, you would have figured that one out. The creative tab that the end user gets to use will have for an icon, an untextured version of what is stored in it, i.e. custom blocks will use an untextured block for the tab's icon. I am doing that on purpose, the untextured block represents something brand new. Quote
Elix_x Posted February 28, 2016 Posted February 28, 2016 I could do that in a future release, but what would you recommend for scripting events via resource pack that forge already has? or are my only options invent something, use a lua module that is in an external jar, or another language jar? Also the word is dynamically and I intend to do more than one mod in a jar. I will do the same with materials and Block.SoundTypes next, then items, then biomes, then entities(yes I mean mobs), then dimensions. The jar won't be called Customcraft for nothing. Besides, the end user will be able to add new blocks, items, etc, from console commands. If you read the dated code above, you would have figured that one out. The creative tab that the end user gets to use will have for an icon, an untextured version of what is stored in it, i.e. custom blocks will use an untextured block for the tab's icon. I am doing that on purpose, the untextured block represents something brand new. Using standart config files will be a pain to do all this. Seriously, go learn json and GSON, and trust me, your life will be over 9000 times easier. Quote Check out my mods: BTAM Armor sets Avoid Exploding Creepers Tools compressor Anti Id Conflict Key bindings overhaul Colourfull blocks Invisi Zones
Recommended Posts
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.