-
Posts
523 -
Joined
-
Last visited
-
Days Won
3
Everything posted by Matryoshika
-
The vanilla trees are placed in worldgen by various classes (WorldGenTrees (oak by default), WorldGenBirchTree, WorldGenSavannaTree etc) which all extend WorldGenAbstractTree, which extends WorldGenerator already. You can take a shortcut, and call WorldGenTrees with the constructor of boolean notify, int minHeight, IBlockState logBlock, IBlockState leafBlock, boolean haveVines . (Notify should be "true", otherwise clients won't see the tree) It will create a normal oak-structured tree for you, with the specified blocks already. This is of course unless you want your tree to have a custom appearance (Like Thaumcraft's or Forestry's trees, for example). For that, you would have to lookup said WorldGen____ classes and see how they use the WorldGenAbstractTree methods. To actually implement the actual worldgen, I would advice you to create a class that implements IWorldGenerator, and then register it in the init phase with GameRegistry.registerWorldGenerator(new NameOfWorldGenClass(), weight); where weight is an integer that states in what approximate order it falls into during worldgen, where low numbers usually go first, high numbers gets placed last. I have an IWorldGenerator that places several different vanilla trees, you can view it here: https://github.com/Matryoshika/Underworld/blob/master/src/main/java/se/Matryoshika/Underworld/WorldGen/Dirty/DirtyTreeGen.java You cannot simply copy paste though (Not saying I thought you would, just that you cannot) because it is used in wordgen that uses a different WorldProvider & BiomeProvider entirely. Ignore the code that references those. I'd advice you to use the generate method to get a blockpos first, using World#getTopSolidOrLiquidBlock(pos) where pos only uses the x & z blockpos gained from the method's chunkX & chunkZ coords. Then, see if the tree can spawn with a boolean method (If the blockpos gained contains grass/dirt (hardcoded check into the WorldGenTree classes, if there's not grass/dirt, it doesnt spawn)). Then, you call your actual generateTree method, that places the tree at the pos#up() coord.
-
Post your current ChunkProvider code. I had a similar issue with really small biomes, in my project a few weeks ago that I managed to fix. Need to see all of your biomesForGeneration setters, to see if you are facing the same issue that I had.
-
[1.10.2] Animated Block is only animated in inventory
Matryoshika replied to SuperHB's topic in Modder Support
The "connection" is made here: ResourceLocation location = new ModelResourceLocation(new ResourceLocation(MODID, blockName), "entity"); return new RenderLiving<EntityChest>(manager, new net.minecraftforge.client.model.animation.AnimationModelBase<EntityChest>(location, new VertexLighterSmoothAo(Minecraft.getMinecraft().getBlockColors())) The code -is- hard to read. It's dynamic in places, like here (blockName is, oddly enough, the name of the block the entity is supposed to be rendered as ), and then hard-coded names in other places. I can't help much more atm, as I'm not too familiar with this type of rendering, though I'll probably sit down and tear the ModelAnimationDebug into their own proper damned classes, to get a better overview of it, in a few hours. Oh, and once again: *Eye twitch* x2 Fix that, please excuse my language, completely redundant, moronic, atrocious and gratuitous use of modid + ":" + getUnlocalizedName().substring() . You have to use setRegistryName(name) for blocks and items. Instead of all that modid & substringing, just use "item(or block).getRegistryName()" and you are done. getRegistryName() already returns "modid:name" for you. Just be sure to set the registryName first, then if you want the unlocalized name to mirror that, use getRegistryName().toString. Registry name is what you use for saying what is what, unlocalized name is purely to describe it in various languages. "...Unlocalized names have NOTHING to do with unique modifiers."-Docmentation of setRegistryName(). I don't fault you for using it, I fault whatever piece of proverbial waste that keep producing tutorials that use that method. -
[1.10.2 - 1249] entityIn.motionZ/X limit?
Matryoshika replied to Dragonisser's topic in Modder Support
-
[1.10.2 - 1249] entityIn.motionZ/X limit?
Matryoshika replied to Dragonisser's topic in Modder Support
You got it the wrong way around. The BB from getCollisionBoundinBox has to be bigger than the one from getBoundingBox. Either make the block return a BB with a smaller y-max in getBoundingBox, or make your collision BB have a y-max > 1.0. Can't get the actual block-registration of the SoulSand block atm, but I believe it has a max-y set to ~0.85, which is less than what the collisionBB returns (0.875) -
[1.10] Getting Forge's current loading state
Matryoshika replied to DBLouis's topic in Modder Support
Have you ever created sided proxies? These events might seem familiar if you have: FMLPreInitializationEvent , FMLInitializationEvent and FMLPostInitializationEvent -
>_< Forgot about the EntityRegistry way. Thanks for reminding me.
-
You can simply add them to the spawnableCreatureList from the BiomeEvent#CreateDecorator event. Create the event-handler, subscribe to the event. The passed argument BiomeGenBase is the biome in question. Check if the biome is ok for your entity to spawn in, and then call biome.spawnableCreatureList.add(new Biome.SpawnListEntry(YourEntity.class, weight, min group count, max group count));
-
[1.10.2] Animated Block is only animated in inventory
Matryoshika replied to SuperHB's topic in Modder Support
You need to clean your code up. I see you have client-only code, in your main. ClientRegistry.bindTileEntitySpecialRenderer(TileEntitySentry.class, new AnimationTESR<TileEntitySentry>(). Hint is in the Client part of the method. Your ClientProxy barely does anything related to rendering. Client is the only side that handles rendering. Do anything with rendering on the server-side, and oooops, crash. You also need to do as the guide shows, and create a new Entity, for your Tile. Also: ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0, new ModelResourceLocation(Refrence.MODID + ":" + block.getUnlocalizedName().substring(5), "inventory")); *Eye twitch* In your IDE: [*]Simply search for the interface "IForgeRegistryEntry" [*]Read the documentation for RegistryNames -
Issue is here: this.addSlotToContainer(new Slot(inv, 0, 30, 17)); this.addSlotToContainer(new Slot(inv, 0, 130, 17)); // Player Inventory, Slot 0-8, Slot IDs 36-44 for (int x = 0; x < 9; ++x) { this.addSlotToContainer(new Slot(inv, x, 8 + x * 18, 142)); } The Slot takes in the parameters IInventory, Index, xPos, yPos. You have to declare the two top slots as something else. You declare the player's hotbar with the id's 0->8, not as the commented 36-44. The player's inventory 9->35. I'd recommend setting the two "main" slots to 36 & 37 respectively.
-
ItemStack#stackTagCompound was replaced with a setter & getter. ItemStack#setTagCompound() & ItemStack#getTagCompound respectively. writeToNBT was changed from void to NBTTagCompound, meaning you have to return the compound that was passed to it, altered or not.
-
[SOLVED][1.10.2] Modifying a vanilla dimension's World Generation
Matryoshika replied to minisantur's topic in Modder Support
Why not simply subscribe to the DecorateBiomeEvent.Post event? Check if the event#getWorld()#provider#getDimension returns 1 (end dimension), and then get the top solid block from event#getWorld()#getTopSolidOrLiquidBlock(pos) (getTopSolidOrLiquidBlock only goes after x & z, and iterates from top to bottom for the first solid block, for you). Then simply change that block, if it is endstone (there's obsidian & bedrock in vanilla End's, modded can add much more) to your End Dirt block. It'd be quite more simplistic with this approach: Only requires an Event-Handler Don't need to override chunkprovider Don't need to worry about other mod's doing the same thing and overriding your chunkprovider (Last one wins the race, here) If you want a "natural" looking dirt depth, like normal dirt over stone in the overworld, you might want to lookup NoiseGeneratorOctaves, or NoiseGeneratorPerlin. You can find some examples in the various vanilla chunkproviders for those. -
Well, there was a similar question a few days ago, about dependencies, which you state you do not want. (Directly referencing another mods' classes, which happen to not exist, even after checking if it was there or not = Crash when creating runtime, because you imported something that doesn't exist.) You can see that conversation here. You want to keep your code as subtle as possible. If you simply want "oh, that mod is in here, let me add this" Then simply use the Loader#isModLoaded(id) to flip a boolean, of which your item/block-registration checks before registering the specified object.
-
public class MyCustomClass extends SomeClass implements ICustomInterface, IOtherCustomInterface
-
A class can extend a single other class. It can also implement several other Interfaces. An Interface is very similar to a regular class, in some points: An interface can contain any number of methods. An interface is written in a file with a .java extension, with the name of the interface matching the name of the file. The byte code of an interface appears in a .class file. Interfaces appear in packages, and their corresponding bytecode file must be in a directory structure that matches the package name. However, the key differences are: You cannot instantiate an interface. An interface does not contain any constructors. All of the methods in an interface are abstract. An interface cannot contain instance fields. The only fields that can appear in an interface must be declared both static and final. An interface is not extended by a class; it is implemented by a class. An interface can extend multiple interfaces. To describe what an Interface is, in layman's terms: An interface provide methods that has to exist in whatever class implements it. If class MyCustomClass implements ICustomInterface, which has a method called myCustomMethod, then MyCustomClass must have a method in it with the same name, and same variables. However, that is all. An interface cannot be used to do anything, only make sure that the methods that actually do the stuff, exists in the class. Interfaces create methods without any body. Just name & variables, like this: static boolean hasEnergy(int energy); It is up to the one creating the class to actually make the hasEnergy method return anything.
-
No documentation? Then what is this? Or that? Here, found a few more pieces: 1, 2, 3. That's all random classes found in the... public GitHub repo. Don't come here and say there's no documentation. How would anyone have made anything using the CoFH API if there was no documentation?
-
Well, energy is simply an amount that goes up and down. You'll need: Storage: how much something can possibly have I/O: How much can enter/leave a suitable storage Generator: A way to get this energy Transport: How to move this energy from point A to point B I would recommend you create your "own API"; make Interfaces that handle each of these points separately (IEnergyStorage, IEnergyInput, IEnergyOutput etc), then create abstract classes that implement these classes, and then, finally create your proper classes, that extend the abstract class. It's a bit extra work, but leaves you with a clean workspace with easy-to-use classes.
-
First, I merely described what each check does. However, there are two ways of fixing the issue: 1) Nest code inside if-statement that checks if it is run on the server if(!world.isRemote){ //do stuff serverside } or 2) have your code do nothing client-side. if(world.isRemote) return; //do stuff serverside
-
If anything, you should only spawn it if !world.isRemote (if not client) or return if world.isRemote (if client) so that the entityItem is only spawned server-side. If you "fixed" it by making the ghost item vanish, then you removed the client-side spawned one.
-
The issue there was solely the "model": "id:block" having been replaced by "id": "block". You are already defining an "inventory" variant in the EEBlocks class. Switch back the "inventory" in your blockstate.json to "normal".
-
[Solved] [1.10.2] Using Mod API Without Using Dependencies
Matryoshika replied to WillR27398's topic in Modder Support
Your question is a bit two-sided when it comes to what you mean. How to check if a mod is loaded? if(Loader.isModLoaded("other_mod's_modid")) //do stuff with things from this mod. How to get rid of dependency, but still make use of X. Dependency is the easiest and most stable way of getting cross-mod interactions. That has to be said. However, for simple things like entities, items, blocks etc, they can all be accessed from strings (Item.getByNameOrId(modid:name), Block.getBlockFromName(modid:name) and EntityList.NAME_TO_CLASS.get(name)) though they should always have null checks, case their name changes or they are, as mentioned, not installed together with your mod. However, for full and complete freedom from dependencies, you want to learn about java reflection, and find classes from strings, instantiate them from scratch, which would be very prone to complete failure should a single thing change in a constructor. It's a long and twisted road to go down if you are not quite adapt with Java. You sure you want to go down it? -
The only "Energy" Minecraft has from the get-go, is simply redstone. If you can't use that, and don't want to make use of power-providing API's, then you are out of luck, unless you feel up to coding your own system, which would in all likelyhood be restricted to only affect your own blocks.
-
"RF" is something provided by neither Minecraft nor Forge. You will have to incorporate another API that allows your blocks to interact with energy-systems. COFHLib seems to be extremely experimental right now, being re-written from scratch for 1.9+, so I would recommend you lookup Tesla API instead. Heard quite a bit of it the last few weeks now, though I haven't actually used it myself. Tesla API can be found Here.
-
To get access to when Player1 hits Player2, I would recommend you subscribe to the LivingHurtEvent and check if both attacker and victim are players, along with whatever other parameters you require. You can get access to the Player's display name from Entity#getDisplayNameString. (Player's extend Entity.) If you are going to do anything with that however, for example saving it, to compare later, I would heavily recommend you use the UUID instead, and simply translate it to the Player's name from the UUID. If the player ever change his name, a name-dependent system will break.
-
GC overhead limit exceeded means that Java's spending more than 98% of the time doing Garbage Collection and retaining less than 2% of the heap. You need to allocate more memory. To quote @shadowfacts Use the org.gradle.jvmargs property in the ~/.gradle/gradle.properties file as described here