Jump to content

[1.9.4] Why is a mod version defined by both the mcmod.info file and the @mod?


Recommended Posts

Posted

Everything I've been taught in my Java classes revolves around unify, unify, unify. There should never be 2 places for the same thing, or a way for you to change a constant that might break the usability of the code. I understand that they're stored different ways, one as a constant within the mod class (presumably) and as text in the mcmod.info text file, but is there any practical way to unify these? Like read the version from the mcmod.info to declare the version constant in the mod class?

 

I've just started to learn how to use git (from this) so that I have version control over my mod projects as I learn, (and have a public host for my code when I request help) but I don't want to have to worry about forgetting to change both version specifications and goofing something up.

 

And yes, I already know that all you FML devs want me to use "MCVERSION-MAJORMOD.MAJORAPI.MINOR.PATCH" for versioning.

Always, RESEARCH before asking a question. It's likely someone has already asked your question in the past. Filter your google searches with "site:www.minecraftforge.net/forum" to have a better chance finding your problem.

Posted

The reason it is in two places is so that repositories (like Curse) can identify the mod version without having to decompile the java classes.

 

If you want to change it in one place, use gradle's

replace

feature to do it for you.

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.

Posted

Oh, well, okay then. I think I'll stick with what I have then. I know nothing about gradle, much less the compile process for forge mods, which is the subject that I immediately come across when I do a quick google search of '"gradle replace" forge'. Hopefully I'll learn something relevant to automating version counting in that git guide I linked to.

Always, RESEARCH before asking a question. It's likely someone has already asked your question in the past. Filter your google searches with "site:www.minecraftforge.net/forum" to have a better chance finding your problem.

Posted

It's super easy.

 

I have this in my gradle build file:

minecraft {
    version = "1.7.10-10.13.2.1291"
    runDir = "eclipse"
    assetDir = "eclipse/assets"
    replace "{@version:lib}":libVersion,"{@version:ore}":oresVersion,"{@version:haz}":hazardsVersion,"{@version:wld}":wildlifeVersion,"{@version:ind}":industryVersion,"required-after:HardLib""required-after:HardLib@["+releaseVersion+"."+majorVersion+",]"),"/*{uncomment}":"","{uncomment}*/":""
}

 

That last, monster, of a line is a list of a->b replacements.  The variables are set up like so:

 

def releaseVersion  = "15"
def majorVersion    = "26"
def minorVersion    = "1"
//bugpatch or testing versions
def libVersion      = "a"
def oresVersion     = "b"
def hazardsVersion  = "a"
def wildlifeVersion = "b"
def industryVersion = "a"
def prePend = "1.7.10-"
def packageVersion  = releaseVersion+"."+majorVersion+"."+minorVersion+libVersion+oresVersion+hazardsVersion+wildlifeVersion+industryVersion

libVersion = releaseVersion+"."+majorVersion+"."+minorVersion+libVersion
oresVersion = releaseVersion+"."+majorVersion+"."+minorVersion+oresVersion
hazardsVersion = releaseVersion+"."+majorVersion+"."+minorVersion+hazardsVersion
wildlifeVersion = releaseVersion+"."+majorVersion+"."+minorVersion+wildlifeVersion
industryVersion = releaseVersion+"."+majorVersion+"."+minorVersion+industryVersion

 

(It is outside of all blocks).  I've got effectively six mods in the same environment, but they're all closely related so I like to test them side by side.  The last replacement is for a chunk of code that I can compile, but not run in Eclipse because Reika doesn't supply deobf versions of any of his stuff.  It was easier to just say "fuck it" and only have the code for release (which now doesn't work anyway, because Reika doesn't realize that APIs are supposed to be a contract saying that they won't suddenly change and cause crashes, not that what I wanted to do in the first place worked anyway because his API was using reflection to access his own methods and was Doing it Wrong).

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.

Posted

Okay, so after taking some time to stare at your code, I think I understand the syntax, but I'm not quite sure how this unifies the numbers. The minecraft portion and the replace command would go something like this I think for me:

 

minecraft
{
   version = "1.9.4-12.17.0.1976"
   runDir = "run"
   replace "{@version:cubex}":cubexVersion
}

I assume that runDir might need to be changed to eclipse? Or do you have your project structured differently? If I change runDir does that change the directory that the game save runs in? I don't know if that would break my compiling completely or not matter at all. I am using 1.9.4 (quickly adds it to the title). The last time I did anything in 1.7.10 was when I was first modding before I had even taken a java class, I was self-teaching myself through the oracle tutorials, so I don't remember any of that. :P

 

Oh, and of course my defines would probably look like this, since I only have one mod (going by the shortened name of "cubex").

 

def mcVersion         = "1.9.4-"
def majorModVersion   = "0"
def apiModVersion     = "0"
def minorModVersion   = "1"
def cubexPatchVersion = "0"

def cubexVersion = mcVersion+majorModVersion+"."+apiModVersion+"."+minorModVersion+"."+cubexPatchVersion

So... how much of this did I get right and how much of it is wrong? Oh, and what exactly does replace replace? Does it only replace the text in my mcmod.info file, or does it override the constant version supplied to @mod in my mod class?

 

Also, thanks for changing that "gradle" earlier to Monaco font. I wouldn't have known that was an available font for in line code if you hadn't done it. I'll be doing that more in the future.

Always, RESEARCH before asking a question. It's likely someone has already asked your question in the past. Filter your google searches with "site:www.minecraftforge.net/forum" to have a better chance finding your problem.

Posted

my rundir is "eclipse", yes.  I don't know what it looks like for other environements (IntelliJ, etc)

 

So... how much of this did I get right and how much of it is wrong? Oh, and what exactly does replace replace? Does it only replace the text in my mcmod.info file, or does it override the constant version supplied to @mod in my mod class?

 

Ok, so.  The only thing I'd change is drop the

mcVersion

from your cubexVersion string.  That can just be on the jarfile, your mod's version number shouldn't need to be prefixed with that (but it's not hurting anything).  I'd probably also swap "major version" and "api version."  Your API should be changing less often than the mod itself and you ABSOLUTELY want the api version change to trigger a mod version change.*

 

As for what the

replace

command does: the paramers passed are comma separated key:value pairs where your entire codebase is searched for the "key" and replaced (before compiling occurs) with the "value."  That's why in the code you use a semi-unique string for anything you want to replace.  Hence the {@} characters.  (Replacing something like "version" would nab

string versionNum = ...

and make that not compile...on account of now reading

String 1.9.4-0.0.1.0Num = ...

).

 

Also, thanks for changing that "gradle" earlier to Monaco font.

 

That's just the code tag. I didn't do anything. :P

 

*You can also do a replacement on your dependency's version numbers!  My numbering system ended up being crap, but it made sense when I started ("number-of-times-released (major)"-"internal (major)"-"minor" and regretted it as soon as I had to fix a bug in the API).  So you could have an "{@version:api}" string in your "required:after" dependency notation in your @mod and let gradle automatically fill that in when your API changes.  Assuming you treat your API like a separate mod (which you should be, so other modders don't need your whole mod in their workspace to integrate with your API).

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.

Posted
my rundir is "eclipse", yes.  I don't know what it looks like for other environements (IntelliJ, etc)

 

Yeah, I'm also running eclipse, I think that the run directory is the same for everything though and mine is default to run just because it's probably changed since 1.7.10 to free up the 'actually for eclipse' folder.

 

That's just the code tag. I didn't do anything. :P

 

Oops, I meant the "replace" in your first post reply, posted here:

 

If you want to change it in one place, use gradle's
replace

feature to do it for you.

 

Which now that I quote you, I see that you just used teletype "<tt>replace</tt>".

 

Okay, now onto the actually important stuff:

 

Your API should be changing less often than the mod itself and you ABSOLUTELY want the api version change to trigger a mod version change.

 

Hmm! This makes sense, I wonder why the FML devs opt for the other order on the documentation. I guess it's not stringent or absolutely necessary, so I think I'll follow your lead.

 

As for what the replace command does: the paramers passed are comma separated key:value pairs where your entire codebase is searched for the "key" and replaced (before compiling occurs) with the "value."  That's why in the code you use a semi-unique string for anything you want to replace.  Hence the {@} characters.  (Replacing something like "version" would nab string versionNum = ... and make that not compile...on account of now reading String 1.9.4-0.0.1.0Num = ...).

 

I had to read that about 10 times, but I get it now. So in my main mod class, I would want to change ... :

 

@Mod(modid = CubularExpansion.MODID, version = CubularExpansion.VERSION,
      acceptedMinecraftVersions = CubularExpansion.ACCEPTED_VERSIONS)
public class CubularExpansion
{
   // STATIC CONSTANTS

   public static final String     MODID             = "cubex";
   public static final String     NAME              = "Cubular Expansion Mod";
   public static final String     VERSION           = "1.9.4-0.0.1.0";
   public static final String     ACCEPTED_VERSIONS = "1.9.4";

   ...

}

 

to ...

 

@Mod(modid = CubularExpansion.MODID, version = CubularExpansion.VERSION,
      acceptedMinecraftVersions = CubularExpansion.ACCEPTED_VERSIONS)
public class CubularExpansion
{
   // STATIC CONSTANTS

   public static final String     MODID             = "cubex";
   public static final String     NAME              = "Cubular Expansion Mod";
   public static final String     VERSION           = "@mcVersion-@apiVersion-@cubexVersion";
   public static final String     ACCEPTED_VERSIONS = "@mcVersion"; // only if I wanted it to only work for the current version

   ...

}

 

I would probably separate mcVersion from cubexVersion and any other mod or api versions I had in my gradle then. I'm already seeing all the advantages of replacing those @variables in my code while programming multiple mods. Oh, and if I put "@mcVersion" in my mcmod.info file, it would also replace that, correct?

 

This is very interesting, very interesting indeed. You've helped me a lot today, thanks for spending time helping me with this. I greatly appreciate it!

 

Thought, your last comment does make me begin to think:

 

*You can also do a replacement on your dependency's version numbers!  My numbering system ended up being crap, but it made sense when I started ("number-of-times-released (major)"-"internal (major)"-"minor" and regretted it as soon as I had to fix a bug in the API).  So you could have an "{@version:api}" string in your "required:after" dependency notation in your @mod and let gradle automatically fill that in when your API changes.  Assuming you treat your API like a separate mod (which you should be, so other modders don't need your whole mod in their workspace to integrate with your API).

 

If I had an API (which I currently don't), I would probably want to separate it and all my other mods into separate gits, so that for each version I could test it on top of a lib of any version of my API or other mods. I'm thinking that I'm going to keep the mcVersion in the version for my mods in case I ever decide to keep support for multiple mc versions of a mod. However, if I use separate gits for each mod, then that would mean I would have to keep them in different project spaces, right? Suddenly another question comes to mind: If I need to make libraries from my other projects, and I have a different build.gradle for a different project, will it overwrite the @version's in that library, or are libraries created from compiled code? like what is generated in the bin folder? I'm going to have to think about this much more later, I must have spent more than an hour writing this. XP

Always, RESEARCH before asking a question. It's likely someone has already asked your question in the past. Filter your google searches with "site:www.minecraftforge.net/forum" to have a better chance finding your problem.

Posted

Oops, I meant the "replace" in your first post reply

Which now that I quote you, I see that you just used teletype "<tt>replace</tt>".

 

Oh yeah. :D <tt> is a great tag.

 

Okay, now onto the actually important stuff:

 

Hmm! This makes sense, I wonder why the FML devs opt for the other order on the documentation. I guess it's not stringent or absolutely necessary, so I think I'll follow your lead.

 

Either one is probably fine.  API for me just seems "more bigger" than their details there, though this is my first time seeing that.  Don't sweat it too much.

 

I had to read that about 10 times, but I get it now. So in my main mod class, I would want to change ... :

 

to ...

 

   public static final String     VERSION           = "@mcVersion-@apiVersion-@cubexVersion";
   public static final String     ACCEPTED_VERSIONS = "@mcVersion"; // only if I wanted it to only work for the current version

 

I would probably separate mcVersion from cubexVersion and any other mod or api versions I had in my gradle then. I'm already seeing all the advantages of replacing those @variables in my code while programming multiple mods. Oh, and if I put "@mcVersion" in my mcmod.info file, it would also replace that, correct?

 

I'd actually do this:

 

   public static final String     VERSION           = "{@cubexVersion}";
   public static final String     ACCEPTED_VERSIONS = "{@mcVersion}"; // only if I wanted it to only work for the current version

 

Which matches the gradle file:

 

def cubexVersion = mcVersion+majorModVersion+"."+apiModVersion+"."+minorModVersion+"."+cubexPatchVersion
//...
replace "{@cubexVersion}:cubexVersion,"{@mcVersion}":mcVersion

 

Just "@cubexVersion" is probably fine (as long as that matches the gradle replace command), but wrapping it in curly braces makes it very clear "this is an external variable."

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.

Posted

Oh, one question I forgot to ask, do the defines in the build.gradle file go in

dependencies {

or something else?

Always, RESEARCH before asking a question. It's likely someone has already asked your question in the past. Filter your google searches with "site:www.minecraftforge.net/forum" to have a better chance finding your problem.

Posted

The defines go outside all of the blocks in the gradle file, eg:

buildscript {
    ...
}

apply plugin: 'forge'

def apiVersion  = "1"
def majorVersion    = "0"
def minorVersion    = "0"

minecraft {
    ...
}

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.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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