Jump to content

GenElectrovise

Members
  • Posts

    132
  • Joined

  • Last visited

Posts posted by GenElectrovise

  1. We're going to need to see the structure of your project.

    Show at least your mods.toml, root Java (the one with the @Mod) and the full structure of your resources and datapack (or at least what you can fit without spamming screenshots everywhere - we basically need as much info as possible)

    Also, how are you exporting it? You should be using the Gradle build task (not the IDEA jar export).

  2. 7 hours ago, LexManos said:

    All I can say is just go do it and see what happens.

    Wise advice for many circumstances. Interesting commit also.

     

    6 hours ago, Draco18s said:

    Case in point, my work project. Which is Unity/C#, but the idea is the same.

    The Unity inspector is pretty good at finding public/serializable values and showing them in a list in the Inspector gui, but it's layout or labels aren't always the best, and there's only so much you can do with annotations (of which there are several). So for more flexibility, Unity offers both a CustomInspector feature and a CustomPropertyDrawer feature (the former is for Unity-objects that appear in the inspector, the latter for miscellaneous objects that are contained within the former).

    However even this is limited to only the things Unity knows how to serialize. Generics? Lists of Interface objects? Abstracts? Not supported.

    But my project needed support for generic objects because of how our interaction system (ECS components encapsulating simple finite state objects) and our grading system (did the user perform the following steps in the prescribed order?) had to integrate with each other.

    I had a hard requirement to be able to display any object Foo in the inspector, regardless of what Foo's type was. So I had to dig into Unity's inspector code and extract out how it handled all of the types it did handle and rewrite it to accept arbitrary values, that if it didn't match the available types, would use reflection to find all of the object's public/serializable fields and then try to draw all of those, recursing down again and again until a primative type was able to be drawn.

    And even with caching to avoid duplicate reflection lookups, it still isn't fast. There's a soft limit of about 20-50 of these inspector drawers that Unity can draw at one time before the lag becomes disruptive. And when you're dealing with complex custom types, the layout isn't pretty. Thus I had to go reimplement Unity's custom editor and custom property drawer system as well.

    Which is to say...if it's more than a handful of very simple objects (ints, strings, booleans...) you're going to have to do the work yourself.

    Thank you - this is very comprehensive and I understand the point that LexManos is trying to make now. This is the explanation I've been looking for.

    I will now close this thread.

  3. 3 hours ago, LexManos said:

    But the cost is quite a lot with mojang liking to re-write the rendering system.

    It seems to me that anything that you'd need in order to make the GUI could be accomplished with #drawString or with Widgets. Is maintaining these the cost of which you speak?

    After all, a config GUI is just rendering a list of keys and a way to edit each value (either toggles or text widgets), no?

    I suppose if you wanted to cut down on maintenance then the first port of call would be to minimise independent calls to volatile 3rd party code (i.e. Minecraft itself).

    Perhaps it is not so simple though... If it was I'd think that someone would have gotten there before me?

  4. 13 hours ago, LexManos said:

    The main reason there isn't one in Forge is manpower to maintain them in the future.

    What would this mean in this context exactly? (Trying to consider whether this project would be a valuable addition to Forge)

    To clarify, does this mean: "any system is too much to maintain, so it's better to just leave it to mod authors"

    Or does it mean: "If we had a more maintainable system, it would be a useful addition"

    I'm basically asking because if it's the former, then I'll only make a screen for my own mods; if it's the latter, then I'll at least have a shot at implementing it in Forge itself :)

  5.  

    13 minutes ago, LexManos said:

    And thee cost of updating it everytime they changed something upstream got too  much.

    If I may ask, what was the bottleneck in updating it? I suppose changes to screen rendering, given you mentioned the rendering guy?

    If I'm going to try to implement my own version, I may as well try to target the problem!! 

  6. Heyo, I'm currently in the process of making a GUI for my mod's configuration options, accessible from "Mods > My Mod > Config" (The whole business of registering an extension point etc). Given the shear number of times poor Diesieben has had to answer the same question of how to achieve this I'd say it's a pretty common query (and why wouldn't it be config is pretty standard stuff).

     

    Why is this config GUI not built into Forge? Is there some secret reason I should know about or has simply noone gotten round to it? Maybe just a decision to let modders implement it themselves? But then surely you could still have a generic GUI and provide a hook for modders to edit or replace it if they choose?

     

    If my implementation is successful enough and testable I may just put in a pull request on the Forge GitHub to implement this. But it does perplex me why this isn't a thing...

     

    All the best to whomever reads this!

     

    P.s. Apologies if I have missed something important: it is very late.

  7. I personally have no idea what could be causing the issue, other than compatibility between some others of your 158 mods. Combining all of those could have some... strange side effects. If you're using an "official" modpack I'd suggest asking on a forum dedicated to that, otherwise you may be in for many hours of debugging (add a mod at a time and see what breaks it). I do not think that it sounds like an issue with Forge. 

    A quick Ctrl+F didn't reveal any errors containing "door" but you probably already looked for that.

    You seem to have two mods which edit doors: mcwdoors and mcwtrpdoors. Perhaps start by looking at those, or other sound mods.

     

     

    Ps. I commend you on the thoroughness of your post - I'd hate to have to ask for logs, etc (that's really tedious)

    1. Whatever your issue is, someone has probably already had it; what have you tried before coming here?
    2. That page does not exist. (The link does not work, code 404. Is the Gist private? Does it even exist?)
    3. Show the contents of start.bat.
    4. What version of Forge are you using (check the lovely banner at the top of the page. If your version isn't supported, you must update)
    5. Minor point, but "Guys can you help me" is not a descriptive title whatsoever. Check my signature for an article on writing a good coding question. Having a good title is helpful for people who have the same issue later on.
  8. I have no idea whether this code would work, but it would go in your mob's renderer class.

    See one of mine here: https://github.com/GenElectrovise/MagiksMostEvile/blob/1.16.5/src/main/java/genelectrovise/magiksmostevile/entity/boss/kitty_the_kraken/KittyTheKrakenRenderer.java

     

    I also have little idea of which method in which to put that code, though the parameters nearly match those of 

    protected void applyRotations(SquidEntity entityLiving, MatrixStack matrixStackIn, float ageInTicks, float rotationYaw, float partialTicks)

    ... so that might be a reasonable place to start? (I know the method name doesn't match - there may be another one which is a better match but I do not have an IDE right now).

    Unless someone with more knowledge can come along and enlighten us, you may need to solve this issue with trial-and-error and vanilla-code-browsing.

  9. Greetings, it's been a while.

    I'd like to intercept chunk loading events so that I can generate new ores in previously explored areas.

    I suppose that I'd listen for ChunkEvent.Load and use event.getChunk(), but the documentation says: "You will cause chunk loading deadlocks if you don't delay your world interactions."... which doesn't sound like a good thing.

    How do I achieve said "delaying"?

  10. Right then. I've tried some thing out over the last few days and come to the following verdict:

     

    Unit-testing Minecraft and Forge classes is really hard. Let me give you an example:

     

    For context, I'm using JUnit 5 with Mockito 3.8

    I have a custom implementation of a fluid tank. I first tried writing a simple unit-test to check that "when there is no fluid in the tank and I try to drain some, drain zero units". I used to extend FluidTank, but in trying to write a simple test, I niow implement IFluidHandler and IFluidTank directly. The reason for this is that creating my object to test, it constructs a FluidTank, which contains this field:

    @Nonnull
    protected FluidStack fluid = FluidStack.EMPTY;

    When FluidStack.EMPTY (a static field) is called on, the JVM tries to also load FluidStack's other static field, FluidStack.CODEC. This in turn causes a cascade of other static initialisations which  culminates in crashing the JVM with a NullPointerException sometime around it trying to either load a World or access a Registry. So not good.

    I tried to @InjectMocks on that field, but the injection occurs after the object is instantiated, so the JVM has already crashed.

     

    In order to get around this, you have to implement the aforementioned interfaces directly because: 1) They are the required interfaces so they have to be there anyway; 2) They contain no static fields, so they won't start a cascade.

     

    The upshot? Forge and Minecraft are not designed to be tested in this way (not surprising), and have interlinking fields with will cause crashes.

    What can we do? Well, you can test anything that you write. You can't test a FluidTank, but you can test an IFluidTank. Try to not have unnecessary static fields, and use constructor injection when possible. (This would fix the problem above: see my code below)

     

    // How to fix that crash
    // In FluidTank.java:
    
    // Don't initialise the field now!
    protected FluidStack fluid;
    
    // Add a new constructor to allow modders to specify a starting stack.
    public FluidTank(int capacity, Predicate<FluidStack> validator, FluidStack initialFluid)
      // Using constructor injection here means that a tester *can* inject a mock object for the initialFluid. This means that no initialisation 		cascade occurs!
        {
            this.capacity = capacity;
            this.validator = validator;
      
      		// Probably a good idea to test the stack for safety.
      		if (!validator.test(initialFluid)) throw new IllegalStateException("Whatever kind of error you want");
      		this.fluid = initialFluid;
        }
    
    // Changing the current constructor to just use the overloaded one.
    public FluidTank(int capacity, Predicate<FluidStack> validator)
        {
      		// This time it's safer to default to EMPTY
      		this(capacity, validator, FluidStack.EMPTY);
        }

     

    I realise that this all sounds very... ahhh... something? (can't think of the word) I'm certainly not the expert on this and I'm not a professional tester so I've probably made some errors or assumptions here.

    I would put this in as a pull request on the Forge Github if I could actually clone it (never works for some reason...)

     

    Best,

    GenElectrovise

  11. Hi all, I've been wondering recently about how one would go about testing mods (I mean testing in a unit-testing sense here).

    Took a look around the MinecraftForge GitHub repo and found the expected src/test/java folder, but most of the tests in here seem to be standalone mods (activated individually with booleans) designed to test a specific behavior.

    Some, however, such as the LazyOptionalTest use JUnit. I suppose this is because game behaviours are really hard to mock-up for testing?

    What's Forge's testing ethos?

  12. Uhhh ok then.

    This is very strange.

    It now works for me too.

    I... uhh... ok then :) 

    Thanks!?

     

    It seems to only store one package at a time? Maybe it only shows the most recent - who knows! I'll look around for this...

     

    build.gradle

    publishing {
        repositories {
            maven {
                name = "GitHubPackages"
                url = uri("https://maven.pkg.github.com/genelectrovise/magiksmostevile") // MUST BE --ALL-- LOWER CASE
                credentials {
                    username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_USERNAME")
                    password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
                }
            }
    		
            maven {
                name = "LocalMaven"
                url = uri("file:///${project.projectDir}/mcmodsrepo")
            }
        }
    	
        publications {
            gpr(MavenPublication) {
                groupId = group
                artifactId = archivesBaseName
                version = version
                artifact jar
            }
        }
    }

     

    gpr.user and gpr.key are secrets contained in my User/.gradle/gradle.properties.

    They are defined like so:

    gpr.user=INSERT_USERNAME_HERE
    gpr.key=INSERT_SECRET_PERSONAL_ACCESS_TOKEN_HERE

     

  13. @DaemonUmbra

    Yes... I would prefer 'maven-publish'... I kept getting the error "Could not write to resource", and Stackoverflow was incredibly unhelpful on the subject...

    'maven' is kind of a stand-in right now...

    Could you send your working publication/build.gradle? The issue is probably with me authenticating but syntax is always an option.

     

    Note: Where are you storing credentials? Naturally they shouldn't be in the project sources, so I'm keeping them in my master User/.gradle/gradle.properties. They seem to be being located there. Are you using a Personal Access Token or standard login credentials? I believe that a PAT is preferred by Github? 

     

    EDIT:
    A PAT is required https://docs.github.com/en/packages/guides/configuring-gradle-for-use-with-github-packages

  14. Thanks @DaemonUmbra - while this thread has been silent I've been wrangling with Gradle...

    I had a lot of trouble (authenticating?) with the maven publishing, so in the end, I have activated the maven (as opposed to maven-publish) plugin, and have set it up like so, which works well.

     

    It requires that I run that uploadArchives command, rather than publish, which I hope won't cause errors with jar re/obfustication (first two lines of snippet).

     

    From the tasks that are run, I can see that the jar is, in fact, reobfusticated prior to uploading (as part of the build process), so I suppose that I'll have to wait and see for the future as to what will work and what not...

     

    jar.finalizedBy('reobfJar') 
    //publish.dependsOn('reobfJar')
    
    publishing {
    	
    }
    
    configurations {
    	deployerJars
    }
    
    uploadArchives {
    	repositories {
    		mavenDeployer {
    			configuration = configurations.deployerJars
    			repository(url: "https://maven.pkg.github.com/GenElectrovise/MagiksMostEvile") {
    				authentication(userName: project.githubGenElectroviseUsername, password: project.githubGenElectroviseToken)
    			}
    		}
    		
    		mavenDeployer {
    			repository(url: "file:///${project.projectDir}/mcmodsrepo")
    		}
    	}
    }

     

  15. How can I publish my mod project to a GitHub package?

     

    I noticed that Forge already has a publishing section in build.gradle, but some of it clashes with the GitHub documentation on this, so I figured Forge might have some requirements for this?

     

    If there is, in fact, nothing special to do, just say and I'll go back to the Gradle and GitHub docs but I thought it'd be good to ask here first :)

     

    Edit:

    The "clashes" I mentioned:

    https://docs.github.com/en/packages/guides/configuring-gradle-for-use-with-github-packages

    publications {
            gpr(MavenPublication) {
                from(components.java)
            }
        }

     

    https://github.com/GenElectrovise/MagiksMostEvile/blob/feature/1.16.4/kitty_the_kraken/build.gradle (Default Forge build.gradle - see line 144)

    publications {
            mavenJava(MavenPublication) {
                artifact jar
            }
        }

     

  16. @Purplicious_Cow

    Hmmm I've also been looking at this: 

     

    Might be a problem with this line:

    On 12/29/2020 at 7:31 PM, Purplicious_Cow said:

    DimensionSettings.field_242740_q.getStructures().field_236193_d_.put(s, STRUCTURE_SETTINGS.get(s.getRegistryName()));

     

    field_242740_q refers to a set of DimensionSettings generated by func_242745_a. That function takes a RegistryKey as a parameter, and in this case, it is passed field_242734_c which is the key for the overworld dimension. That might be the issue? Don't quote me on this! I have the same issue as you, but for all dimensions!

    • Thanks 1
  17. @CaiGuyCrafter

    "We" refers to the members of this forum, which is for people modding using Forge directly, not MCreator.

     

    Given that you are using MCreator, I would recommend using the MCreator forum https://mcreator.net/forum.

    Mixing auto-generated code with human-written stuff sounds like a pretty gruelling experience to me, but maybe someone there can help.

     

    If you want help with Forgeyou've come to the right place. Only Forge though.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.