jabelar
Members-
Posts
3266 -
Joined
-
Last visited
-
Days Won
39
Everything posted by jabelar
-
[1.12.1] Help with 2 small errors that i dont know how to solve.
jabelar replied to Anonymous1611's topic in Modder Support
I know is sometimes sounds mean to tell people "learn Java". But your problems really are simple Java things that have not much to do with modding specifically. So I really suggest learning Java more solidly. I suggest a very good, simple book called Java In Easy Steps. I like the book because it is very short but still covers the major topics. So you can get through it quickly, and it isn't boring or "scary" like some of those "Java for Dummies" types of books. Your first problem is very clear, you're trying to assign a type to a value that is not of that type. The return type of the armor inventory is a NonNullList<ItemStack> and you're trying to put that value into an ItemStack[] (an array of ItemStack). If you really need an array you can convert -- in fact the NonNullList probably has a method to help you do that. But you can also just keep it as a NonNullList and use list type of methods for looping through and checking values. Your second problem is also very clear, you are trying to use a field or method which does not have public scope. That means you cannot access it from outside the class (or package or hierarchy depending on what the scope actually is). You really need to study the concept of scope in programming. In particular Java has public, protected, private (plus some other cases like local) that can control "visibility". To fix this problem, the first thing you need to do is see if there is a public "getter" method for the private field. For example, maybe there is a getBoundingBox() or similar method available. -
I think it is possible using similar technique as an extended reach weapon. Basically, you need the client side to do custom ray-tracing where you would ignore the grass block, and then send custom packet (or maybe attack keybind) to server where actual attack gets processed. I have a tutorial on extended reach here: http://jabelarminecraft.blogspot.com/p/minecraft-modding-extending-reach-of.html It would take a bit of work, but I think it is possible.
-
Okay, so thinking about it more, yeah I think you've kinda messed up the sides thing. Also, your key processing isn't efficient as you shouldn't have to do it every tick but rather only on the KeyInputEvent (which will process changes in the keybind state). I have a tutorial on keybinding here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-1721710-keybinding.html which shows a bit more about using the KeyInputEvent. Basically, you need to organize the code in the following way: 1) Register your keybind in your client proxy. 2) Since KeyBinding class is SideOnly for Side.CLIENT you cannot reference that class outside of your proxy or at least in a sided piece of code. 3) You should handle the KeyInputEvent, and while technically that class isn't annotated as client side it is only fired on client side and you're going to need KeyBinding in the method so you need to have your KeyInputEvent handling method sided. I personally just put it in my client proxy. 4) In the event handling method, when you detect that the keybind has been pressed you need to send a custom packet to the server. 5) When client receives the custom packet it should set the size of the player bounding box appropriately.
-
Have you tried using the B+F3 combo to turn on the visibility of the hitbox? So you can confirm it is actually applied as you expect? Is it just the bigger size, or also small size that is not working? I'm wondering if it is an issue with the side the code is running on. The keypressing is on the client but the server needs to "know" if the hitbox has changed as well for things like navigation. In your code above it isn't clear if you've set up the keybinding properly to make sure both sides are aware of the press.
-
The biome class has a genTerrainBlocks() method where you can do whatever you want.
-
Where's your code where you register the block models and item block models? Also, do you see any console or logger errors related to missing models or textures? Post the console log. Lastly, these things are always a matter of the details. I would add even more print statements to make sure everything, like the registry names and such are fully correct. You can also use debug mode in your IDE to check this.
-
Depending on how you do the event subscribing, the method can need to be static. Draco18s knows the details and can explain better. But basically trying making your method static.
-
how to call non random updateTick for blocks Forge [1.12]
jabelar replied to JavaMan7's topic in Modder Support
I never said TEs have to tick. Regarding scheduled ticks, you're right I forgot about that mechanism. But again none of these save him anything. Ticking a block is easy -- at least five simple ways come to mind to do it. But there is a reason why there are special mechanisms for ticking -- anything that tries to tick a lot of blocks will have potential performance problems. My answer is mostly reacting to fact he's talking about "dirt" blocks which I assume would form a lot of surface. If he's only placing these occasionally like redstone-based things, then sure use scheduled. Also, I would suggest that random isn't necessarily that bad. Vanilla ice blocks melt randomly, so turning a "frozen dirt" to "dirt" with random ticking is very consistent with way Minecraft already treats melting blocks. -
I have some tutorial information on world generation (including biomes) here: http://jabelarminecraft.blogspot.com/p/minecraft-forge-1721710-biome-quick-tips.html
-
how to call non random updateTick for blocks Forge [1.12]
jabelar replied to JavaMan7's topic in Modder Support
You have to remember that any Minecraft world ends up with literally millions of block positions. Each chunk alone has 65k block positions! So for performance and memory/storage reasons, only a little bit can be done with blocks. So you can't have lots of blocks ticking or it will cause a performance problem. Of course it is nice to have some blocks that change over time so there are two options -- tile entities (which really just means a "ticking block position that can contain extra data") or random ticks. Of course you can try to do your own ticking by handling a world tick event and scanning blocks but that would cause performance problems. So the main way to have your block tick is to assign a tile entity. However, it sounds like you want to replace a lot of blocks since you're calling it "dirt". That will still be a problem because a lot of tile entities will have same problem with performance. Basically I'm saying there isn't really any way you can have a lot of blocks (like dirt) ticking constantly without a serious performance impact. But if you want to try, you should use tile entities as that is the optimized way of ticking a block position. -
[1.12.2] Problem with SpongeForge / mixin as library from a cloned repo
jabelar replied to jabelar's topic in Modder Support
I'd like to know if this is a generic thing with using libraries, or specific to mixin -- If the build.gradle has downloaded the library and it shows up properly in my referenced libraries, is there any need to separately "install" the library JAR or manually do anything in the build path? -
It is actually fairly easy actually. Regular Java reflection is well documented so you can find tutorials, but in modding it is a bit tricker because you need to be able to have the reflection work both in the development and final build environments. So ReflectionHelper does reflection but helps map it to both situations by passing both the debfuscated and SRG names to the methods. The idea generally is to store the reflected field or method in an instance, For example to access the "fire" field in Entity class something like: public static Field fire = ReflectionHelper.findField(Entity.class, "fire", "field_190534_ay"); Then if I wanted to access it to get or set the value I might do something like: if (theEntity.isImmuneToFire()) { fire.setInt(theEntity, fire.getInt(theEntity) - 4); if (fire.getInt(theEntity) < 0) { theEntity.extinguish(); } } The only trick is that in the ReflectionHelper you can see I entered both the string "fire" and "field_190534_ay". To find that second string you need to use the MCPBot (or download the MCP mappings and search through them to find the right one).
-
So I am trying to run (in Eclipse) some code I cloned for a SpongeForge hybrid mod. It is a private repository so I can't post much of it here, but I have a general question. The gradle/maven from the build.gradle seems to properly download SpongeForge and related things like "mixin" and I can see it in my referenced library just fine. The build.gradle looks like: buildscript { repositories { jcenter() maven { name = "forge" url = "https://files.minecraftforge.net/maven" } maven { url = "https://plugins.gradle.org/m2/" } } dependencies { classpath "net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT" classpath "gradle.plugin.org.spongepowered:spongegradle:0.8.1" classpath "com.github.jengelman.gradle.plugins:shadow:2.0.2" } } apply plugin: "net.minecraftforge.gradle.forge" apply plugin: "org.spongepowered.plugin" apply plugin: "com.github.johnrengelman.shadow" version = modVersion group = modGroup archivesBaseName = modBaseName minecraft { version = project.forgeVersion runDir = "run" // the mappings can be changed at any time, and must be in the following format. // snapshot_YYYYMMDD snapshot are built nightly. // stable_# stables are built at the discretion of the MCP team. // Use non-default mappings at your own risk. they may not always work. // simply re-run your setup task after changing the mappings to update your workspace. mappings = project.mcpVersion // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. } repositories { mavenCentral() } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } dependencies { compileOnly 'org.spongepowered:spongeforge:1.12.2-2611-7.1.0-BETA-2931' compile 'org.mongodb:mongodb-driver:3.4.3' } processResources { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version // replace stuff in mcmod.info, nothing else from(sourceSets.main.resources.srcDirs) { include "mcmod.info" // replace version and mcversion expand "version": project.version, "mcversion": project.minecraft.version } // copy everything else, thats not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude "mcmod.info" } } build.dependsOn(shadowJar) However, when I run the client run configuration I get the following error: The key error seems to be that it is saying there is "func_70932_a_ does not exist in target interface net.minecraft.entity.IMerchant" However, if I check MCPBot that function does exist and is related to merchant interface. Other people who clone the repository and run it in IntelliJ say it works. However, they also say I need to separately download the SpongeForge JAR and put it in my "mods" folder. However, I feel that is not correct because I already see it in my referenced libraries (Maven has already downloaded it) and also I would need a deobfuscated version of the JAR which I can't find -- I think they mean I need to download it if I actually build the mod and try to run it normally. I'm trying to run inside Eclipse using the Run Configuration. So a couple questions: - There is also the earlier warning "Unable to instantiate org.fusesource.jansi.WindowsAnsiOutputStream". Is that a problem, and if so how to fix? - If I already have the JAR downloaded and referenced automatically with gradle/maven, do I really also need to download the JAR separately as well in order to run in Eclipse? - Why would mixin be having trouble finding a function which should exist? - Any other tips for using SpongeForge library?
-
You should learn to use the Call Hierarchy to figure out such things. I didn't know the answer but just used that to find out myself. Programmers don't usually know this stuff off the top of their head, but rather know how to use their IDE (I use Eclipse) to quickly confirm and follow code. Anyway, in this case your creative tab class should have a method called displayAllRelevantItems() or if your class doesn't have it you should @Override it from the parent class. That method takes in a list as parameter that gets populated with the items, so you could just use standard list methods for filtering or removing items.
-
It is pretty tough. That is why there is currently a PR to add Forge hook for custom Elytra. See https://github.com/MinecraftForge/MinecraftForge/pull/4476
-
The black in the transparent fields is a problem where leaves are hard-coded for honoring the fancy graphics setting. For custom leaves it is very difficult to make your leaves honor that setting, so I just make it always fancy for my own leaves. You can look at how I do it in my own custom leaves: https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/blocks/BlockLeavesCloud.java In the constructor you can see I call a proxy method to set the graphics level to always be fancy. You should do the same -- you'll also need to look at my code in my ClientProxy and ServerProxy classes. It is possible but tricky to get the fancy setting to work as a user setting. There are other threads on that if you really care. I personally think anyone who needs to turn off fancy settings should get a new computer!
-
When you have a game engine where an object is moving fast you need your collision logic to handle that. So instead of moving all 3 spaces at once you actually should loop 3 times with a 1 space move. Then your wall-checking should work. In other words, when collision checking a fast moving game object you need to check the positions in between as well.
-
No, as I mentioned the vanilla coding is strongly inclined towards and "all or nothing". Basically the Item gets a creative tab and the getSubTypes() populates the list with all the variants. For your own Item classes you have full control over the getSubTypes() but not for the vanilla classes. The only publicly accessible control is at the Item level and even reflection won't help because the return values are coded right in the methods -- there are not fields that can be manipulated.
-
There might be a clever way to do it, but it looks tricky. The key method is actually the getSubItems() method. It takes in a list that is provided by the creative tab gui and populates it with all the variants of the item. I'm not aware of a good Forge hook for it. Basically, Minecraft seems to be strongly coded such that all variants of an item are intended to go on the same creative tab(). I think the "easiest" way is to actually create your own extension of the creative tab GUI and use the GuiOpenEvent to replace the vanilla one with yours. In yours you could filter out the results of the getSubTypes() method in any way you wished.
-
As always, don't just speculate -- actually trace through the execution to see what is happening. Either use debugger mode or console (System.out.printf()) statements to see what is going on. For example, you see which loot table is actually being loaded for the event and then you can inspect that table to understand if there is a different pool name. Technically if you look at the LootTable$Serializer class you'll see that the name is extracted using the ForgeHooks.readPoolName() method. In that method, there are various cases where the pool could be named in the actual JSON, but if not then it is according to the following return statement: return ctx.poolCount == 1 ? "main" : "pool" + (ctx.poolCount - 1); So that means that it could be named "main" but could also be named "pool0", "pool1", etc. And it could also have a custom name if the "name" is assigned in the JSON (although looking through the vanilla loot table JSONs I don't think it is used there). So now that I think about it, if you want to add your loot to every pool in every loot table you would really want to access the pools field in the loot table. The problem though is that it is private and does not seem to have a "getter" method. Therefore, I think you need to use Java reflection to make the pools List accessible, and then you should iterate through that list and add your item. Now that I think about it, it is kinda lame that loot table pools list is private. Maybe I'm missing something, but it seems to me that it could be useful. Otherwise you need to know (or guess) at the pool names. If you want to handle the vanilla pools, then you can probably not use reflection but rather just "guess" at the names since you know that they will either be "main" or "pool0", "pool1", etc. So you can create a loop that tries to get each of those pools and checks if it is null and escapes the loop once it runs out of possible pool names.
-
You need a few things all correct, such as the shouldSideBeRendered() and the render layer, etc. Is your block extending BlockLeaves? If so then it should already work unless you're overriding the block methods improperly. Otherwise just inspect BlockLeaves and make sure all the code related to rendering is copied.
-
As far as I know the change to JSON files only was for block and item models, and entity models are still "hard-coded" in model classes. For example, look at the ModelWolf class. The main idea is that you need a render class and a model class (look at RenderWolf and ModelWolf for ideas) and then you need to register the render class for your entity. The model class is called by the render class. Basically you should be able to get started by actually calling the wolf. You won't be able to "import" the animations unless you use some sort of animation API. But if you want it to have similar animations to the wolf (it will walk around, wag its tail, sit down, etc.) you can pretty much just copy the wolf code.
-
Cool. I think the big learning is having the skills to track down these things yourself. As long as you can observe the execution of a program you can always debug it.