Jump to content

How to publish a forge based library?


jcranky

Recommended Posts

Hi,

 

I'm developing a lib I want to be used by mods. The lib uses forge, and the mods will use forge as well, obviously. Do I have to take any kind of special care when generating the jar file for the lib, or can it be generated with a simple

 

./gradlew build

 

?

 

I'm asking because in my tests some methods are causing crazy NoSuchMethodErrors like the one bellow when used in the 'client' mod, which makes me think that something might be "out of sync" here.

 

[01:35:48] [specs2.env1591740272-2/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]: java.lang.NoSuchMethodError: net.minecraft.item.ItemStack.func_82833_r()Ljava/lang/String;
[01:35:48] [specs2.env1591740272-2/INFO] [sTDERR]: [java.lang.Throwable$WrappedPrintStream:println:748]:        at com.easyforger.recipes.package$.toRecipeItemStack(package.scala:12)

 

The package.scala:12 mentioned in the error contains the following:

 

implicit def toRecipeItemStack(itemStack: ItemStack): RecipeItemStack = RecipeItemStack(itemStack, itemStack.getDisplayName.toLowerCase.charAt(0))

 

My guess is that itemStack.getDisplayName is to blame. Makes sense?

 

thank you!

 

[]s,

just you wait! ;)

Link to comment
Share on other sites

Perfect! Worked like a charm, thank you.

 

Now let me just understand what is happening here. I just need the deobfJar task, plus the extra tasks.build.dependsOn definition, right? I see you also defined a sourceJar task. Why? It worked without that for me, but perhaps I'm missing something that I'm just not seeing?

just you wait! ;)

Link to comment
Share on other sites

I was looking at this and couldn't get it to work, as I want to have a deobfuscated package that is only one of my packages.  I've got various sub-mods all using the same build script, and while I did get a deobf version, it was everything, not just my lib.

 

So I'm not sure how to combine that build entry with something like

    from zipTree(jar.outputs.getFiles().getSingleFile()).matching {
        exclude 'com/draco18s/ores/**', 'com/draco18s/hazards/**', 'com/draco18s/wildlife/**', 'mcmod.info'
    }

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.

Link to comment
Share on other sites

Draco18s, that is not a concern for me because I want everything. Perhaps that could be a way for you as well. Separate what is not part of the 'exported' lib in its own project.

 

In my case, I'll have three projects: the lib, a tester, and samples. Its a bit more trouble setting up but everything gets nicely organized. The main down side is having to publish the library 'all the time', which is not that hard if you publish to maven local.

just you wait! ;)

Link to comment
Share on other sites

The source jar is not needed, but I have it so that people who use the library can see e.g. the javadocs and not get decompiled code when looking at the classes in the library. But technically it is not needed.

 

So the main goal is getting the sources jar? I'm already getting that, I thought this was a standard task from gradle, but perhaps that is my publish plugin doing? I don't need sourceJar even here (tasks.build.dependsOn('sourceJar', 'deobfJar')) then?

 

Also, where does the deobf classifier comes from? ForgeGradle plugin?

just you wait! ;)

Link to comment
Share on other sites

Draco18s, that is not a concern for me because I want everything. Perhaps that could be a way for you as well. Separate what is not part of the 'exported' lib in its own project.

 

Yeah, I could probably do that at this point.

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.

Link to comment
Share on other sites

  • 2 weeks later...

So, I've been thinking about this a little. To use the published library, I'm having to do

 

compile 'com.easyforger:easyforger-core:0.1-SNAPSHOT:deobf@jar'

 

Point being: I'm having to specify the classifier. Is that what should happen? Also, is the 'normal' (non deofuscated) jar file of any usage in this scenario?

 

thanks!

just you wait! ;)

Link to comment
Share on other sites

I see. So the deof is for the mod author to compile against my library, but for the client to run that mod, the normal jar will have to be installed in the mods folder. This also means that creating an uber jar is a bit more complex.

 

In that regard, would that be a good idea (the uber jar)?

just you wait! ;)

Link to comment
Share on other sites

Do those dependencies include mods? If so, that's a bad idea.

 

No, I'm mainly concerned with the library itself, that will not contain any mods. I just want to make using the library as seamless as possible. All sample mods using the library are going to be in a separated project.

just you wait! ;)

Link to comment
Share on other sites

Yeah.... that's a very complex problem. Handling libraries manually takes us back 15 years ago, before even maven was around... having to manage libraries, and libraries of libraries.

 

Coming to think of it, this can affect the libraries of my library as well. Which means that, to be really safe, it would be better to avoid any external libraries at all... or am I taking this rationale too far?

just you wait! ;)

Link to comment
Share on other sites

Are you sure you want to create a library, or maybe you just need to publish an API -- i.e. just expose those methods that you are actually interested in providing to other modders?

 

Alternatively, if you're just keen to share useful code maybe just leave it open source and people can copy it and modify it directly if they wish.

 

I feel like publishing a library is a bit grandiose because it implies (at least I only undertake it if it has) a very high degree of general usefulness. What is the functionality this library would provide?

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Are you sure you want to create a library, or maybe you just need to publish an API -- i.e. just expose those methods that you are actually interested in providing to other modders?

 

And how would the modders use that API? Expose where?

 

Alternatively, if you're just keen to share useful code maybe just leave it open source and people can copy it and modify it directly if they wish.

 

It is open source already. I'm just not promoting it too much because it is just starting and there are lots to be done still. It should be a library because there won't be any reason to change the code of the library. The internals are likely to get complex and easy to break if you don't know what you are doing. Like forge itself, it should be used, not messed with.

 

I feel like publishing a library is a bit grandiose because it implies (at least I only undertake it if it has) a very high degree of general usefulness. What is the functionality this library would provide?

 

Yes, the goal is to be quite comprehensive. I'm writing wrappers and DSLs on top of forge, with Scala. :D

just you wait! ;)

Link to comment
Share on other sites

An API and a library are one and the same, the API being the public interface to the library.

 

Semantics aside, they are used in exactly the same fashion: developers use a deobfuscated jar and everyone else uses the normal jar.

 

My point is more the attitude about how the code is organized and presented. a professional library of course has a well managed API. But a person could create a library where everything is exposed or something and make a mess of it.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

An API and a library are one and the same, the API being the public interface to the library.

 

Semantics aside, they are used in exactly the same fashion: developers use a deobfuscated jar and everyone else uses the normal jar.

 

That's how I see it, and that's why I was a bit confused with jabelar's first statement.

just you wait! ;)

Link to comment
Share on other sites

My point is more the attitude about how the code is organized and presented. a professional library of course has a well managed API. But a person could create a library where everything is exposed or something and make a mess of it.

 

Everything is exposed anyway, unless we use classloaders tricks. So yes, organization and presentation are important. But technically, its all the same and that's where I'm getting at. So I'll have to remember to have both a developer's and a user's guide.

 

Or on a second thought... installing the library seems to actually be part of the mod installing process. Does this make sense?

just you wait! ;)

Link to comment
Share on other sites

An API and a library are one and the same, the API being the public interface to the library.

 

Semantics aside, they are used in exactly the same fashion: developers use a deobfuscated jar and everyone else uses the normal jar.

 

That's how I see it, and that's why I was a bit confused with jabelar's first statement.

 

Sorry for the confusion. Almost everything has an API of course. But I think the attitude is different when creating a library versus "just another mod with an API". When I provide a rudimentary API to mod my mods I wouldn't go as far as calling the result a library.

 

Furthermore, even though the Minecraft decomp source are a referenced library, they are in my opinion not proper libraries because there is public access to all sorts of stuff that isn't really intended as the modding API.

 

Maybe it is just me. To me a library has a high standard of intention behind it, not just any decomp code that you dump into your referenced libraries.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Maybe it is just me. To me a library has a high standard of intention behind it, not just any decomp code that you dump into your referenced libraries.

 

Well, yes, I can agreed with that. It is different to say that your mod has an API, and that your mod is a library. And that is also why I am calling my thing a library: it is not a mod. It is a set of wrappers and helpers intended to help mod creators.

just you wait! ;)

Link to comment
Share on other sites

So yes, organization and presentation are important. But technically, its all the same and that's where I'm getting at. So I'll have to remember to have both a developer's and a user's guide.

 

That's really my point.

 

I was worried that you're just taking a cool mod that you did and trying to re-purpose it as a "library". Someone just saying "I want to make a library" sounded suspiciously naive. However, you obviously know what it means: you're trying to build up a grounds-up codebase intended for multi-coder use from the start.

 

I'll be quiet now...

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Sorry for the confusion. Almost everything has an API of course. But I think the attitude is different when creating a library versus "just another mod with an API". When I provide a rudimentary API to mod my mods I wouldn't go as far as calling the result a library.

 

Furthermore, even though the Minecraft decomp source are a referenced library, they are in my opinion not proper libraries because there is public access to all sorts of stuff that isn't really intended as the modding API.

 

Maybe it is just me. To me a library has a high standard of intention behind it, not just any decomp code that you dump into your referenced libraries.

I was just pointing out that any exposed part of a library/mod is an API and that the way to use an API, whether from a mod or a library, is identical.

 

It would of course be silly to call a mod with some exposed methods a library, even though that would be semantically correct :P

Link to comment
Share on other sites

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.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I have been currently having this issue where if I join my server, I get one of these 2 errors. I have tried fixing this issue by looking at the output log in both Server and Client side, from what I have seen I was not able to find anything I can understand that would have helped me. These two errors pop up randomly with no pattern when attempting to join the server when it says Encrypting... I have tried removing all mods from the Client and Server side, which did nothing and still showed the same errors (I don't remember which error showed or even if it showed both), so from what I tried to do, I do not think this is a mod Issue but rather a Forge Issue. How do I fix this? Here are the errors and all the information: Internal Exception: java.lang.NoClassDefFoundError: com/google/common/util/concurrent/TrustedListenableFutureTask Debug.log: https://www.mediafire.com/file/hbtycb1tamqt1qr/debug2.log/file (PS: Debug.log file cannot be uploaded to Pastebin due to it crashing because of the Large Amount of Spam OpenGL logs) Internal Exception: Internal Exception: java.lang.NoClassDefFoundError: com/google/common/collect/LinkedHashMultiMap$ValueSet Debug.log: https://www.mediafire.com/file/o1d48z0bjfyff1e/debug.log/file (PS: Debug.log file cannot be uploaded to Pastebin due to it crashing because of the Large Amount of Spam OpenGL logs) Client Mods: Server Mods:
    • the removing of the Material class has mess up bad mi code now have to many broken things after updating mi code to 1.20.4 this are mi pipes they conect each others but to have it right i have to made a custome BlockItem  the thing its that i need to check the block im looking at  if its some something like grass or wheat i need to ignore and replace whit mi pipe block but if its something like leaves then it must respect it and set the pipe above or at the side  in x < 1.9just check the material the target block is made of     in 1.20 cannot be done like this soo i was trying to make a list of solid blocks but is much work and also it don't have in account blocks from other mods              
    • tysm, ur a life saver,, its weird immersive portals became the issue because I play-tested the mod pack once and everything ran, it only started crashing when I tried playing it a second time.
    • could it be by making a custome block whit no hitbox  or by a falling block entity  // ########## ########## ########## public FallingBlockEntity create_FallingBlock(BlockPos cursor){ this.fallingblock = FallingBlockEntity.fall(warudo, cursor, this.getBlockState() ); this.fallingblock.setNoGravity(true); warudo.addFreshEntity(this.fallingblock); return this.fallingblock; }
    • in 1.19 i notice that an have to fix by hand  in 1.20.4 this is not a problem anymore but 1.20 has its own set of new problems   // ########## ########## ########## ########## // lista de entidades atravezadas por la linea entre vi y vh|vo public ArrayList<LivingEntity> findHitEntitys() { return findHitEntitys(0.0D); } public ArrayList<LivingEntity> findHitEntitys(double grow) { double hgrow = (grow/2) * -1; Vec3 vi = this.subject.getEyePosition(); Vec3 vo = (this.vh != null) ? this.vh : this.vo; /* Double xn = Math.min(vi.x, vo.x); Double xm = Math.max(vi.x, vo.x); Double yn = Math.min(vi.y, vo.y); Double ym = Math.max(vi.y, vo.y); Double zn = Math.min(vi.z, vo.z); Double zm = Math.max(vi.z, vo.z); Vec3 vdi = new Vec3(xn,yn,zn); Vec3 vdo = new Vec3(xm,ym,zm); */ // particle(warudo, vo); AABB bb = new AABB(vi, vo).inflate(2.0D); //System.out.println( (bb.maxX - bb.minX) + ", " + (bb.maxY - bb.minY) + ", " + (bb.maxZ - bb.minZ) ); ArrayList<LivingEntity> list = new ArrayList<LivingEntity>(); Predicate<? super Entity> cosa = target -> (target instanceof LivingEntity);// for (Entity target_entity : this.warudo.getEntities(this.subject, bb, cosa)) { //System.out.println(entity1.getBoundingBox()); // is the entity in the line //if (entity1 instanceof LivingEntity) { AABB aabb = target_entity.getBoundingBox().inflate(grow); //System.out.println( "x " + (aabb.maxX - entity1.getX()) + ", " + ( entity1.getX() - aabb.minX ) ); //System.out.println( "y " + (aabb.maxY - entity1.getY()) + ", " + ( entity1.getY() - aabb.minY ) ); //System.out.println( "z " + (aabb.maxZ - entity1.getZ()) + ", " + ( entity1.getZ() - aabb.minZ ) ); Optional<Vec3> optional = aabb.clip(vi, vo); //System.out.println(aabb); if (optional.isPresent()) { list.add((LivingEntity) target_entity); } } } list.sort((o1, o2) -> (Double.compare(o1.position().distanceTo(vi), o2.position().distanceTo(vi)))); return list; }   1.20.4 has not this problem anymore
  • Topics

×
×
  • Create New...

Important Information

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