Jump to content

Forge MP, Bukkit and Minecraft 1.3


Kinniken

Recommended Posts

Hi,

 

I'm the author of a fairly large mod, Millénaire. So far I've kept it SP only, not because I'm against an MP version but because there seemed to be too much fragmentation of MP APIs and no solution that would allow me to keep the SP and MP code synchronised without having to maintain two wholly separate branches. However since in Minecraft 1.3 SP will basically be MP with an integrated server, I'm going to have to do the conversion anyway. One possibility is to go with Forge, but for that I have a few questions:

- does anyone know whether the changes in Minecraft 1.3 mean that Forge will support SP mods using its current MP APIs?

- what is the status of Forge and Bukkit? Can Forge MP mods be run on a Bukkit server?

- has anyone heard anything official from Mojang or the Bukkit people working with it on how mods are expected to work in Minecraft 1.3?

 

Thanks

 

K.

Link to comment
Share on other sites

  • Replies 102
  • Created
  • Last Reply

Top Posters In This Topic

These questions were one of the main reasons we decided to do fml client now rather than wait for 1.3.

 

For fml (I cannot speak for forge) my goal is that everything you have right now will live on into 1.3, in some fashion. Things that no longer will make sense on the client side (game ticks f.e.) will probably stop working, but only on the client side.

 

As for your bukkit question: I maintain the port of forge for bukkit so hopefully that will continue as long as the bukkit project itself does.

 

To your overall question now is the time to plan smp forge smp (esp for custom entities) is very strong now. I recommend you use forge and start planning. Smp migration though not trivial is not as hard as it might appear. I refer you to iron chest and compact solars as two projects on github that you can examine for organizational tips so you don't have to fork everything in your code base for amp.

 

Github.com/cpw/iron chest and github.com/cow/compactsolars

 

Hope this helps!

Link to comment
Share on other sites

Thanks for the answers! That's rather promising. Stupid question though, how do I access those GitHub repos? I'm old-fashion, I use SVN for Millénaire ;)

 

And with that Forge for Bukkit, do you have to release Bukkit versions of SMP mods or can it load the regular one?

 

Github repos need git to access them. Github has a crapton of help. Or you can just view them through the browser if you want to simply reference them...

 

Bukkit does require a "bukkit" version be generated- this is mostly a matter of converting the MCP based API to the bukkit based one. There are a variety of solutions to this and it's an active area of research at the minute- for now, assume that once you've built your mcp based SMP version, there will be a way to create a bukkit version from it. I will refer you to mcportcentral.co.za for examples from other mods that do this right now, though the process there is a little bit clunky at times ;)

 

On your last question there is no information that I have seen at all. I believe there's "hidden" work on the API going on, but that the 1.3 changes are so that the API (which is likely 1.4) can be SMP only...

Link to comment
Share on other sites

Thanks for the new info. Also, nobody really knows when 1.3 will be released, right?

 

I've setup a Forge MCP environnement, I'll start checking out the APIs. Any good references that you know on migrating from SP to MP? I'll have to deal mainly with custom entities, world generation, custom items and blocks, several custom GUIs, server-side actions based on client-side keyboard presses, read/write to the server's mod folder and the world's folder, keeping track of the positions of the players, and some custom entity rendering based on custom entity properties. I think that's the bulk of the areas that should be impacted by the switch to MP.

Link to comment
Share on other sites

Never used your mod but from what i've heard its good. Anyways from my experiences with NPCs there really easy to port to smp. They just need some dataWatchers to share variables between server and client. Sometimes they need to interface IMob or IAnaimal.

GUIs i don't know much about and still need to create a few for my NPC mods but, they need some kind of GUI handler and maybe a packet system. Land gen i think is done the same way, so are block and items. TileEntities are the same as well but you might want to code your ssp to not do anything when connected to a Server. No need for fake NPC to spawn ssp and not actual be there.

 

Porting in general you need to remove all graphics code from your smp code. Things like renders,  Guis, names, special effects and such. You also need to make packets too send any special data too the client that is generated from the server.

Link to comment
Share on other sites

Shameless OS plug: If you toss up a github repo i'd be more then happy to sit down and help you clean up and get thing working properly on SMP. Especially if you're saying you're gunna drop that whole annoying 'Forge Lite' crap. That is really annoying.. hehe

 

Anyways, Forge and FML are designed to keep the modding API fairly consistent, while still allowing for active development. However when it comes to 1.3, there will be many things that are different but I plan on making 1.3 as easy to merge to for modders as I can.

As there is no public official information on what exactly is changing under the hood of Minecraft I can not garentee that it will be instantly compatible, but it'll be as easy as I can get it.

 

Gitting your environment setup for SMP work, and then tackling each task one at a time would be the best method of getting help I think.  Feel free to ask as many questions as you need.

 

 

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

Shameless OS plug: If you toss up a github repo i'd be more then happy to sit down and help you clean up and get thing working properly on SMP.

 

Thanks. I'd like to try doing it myself first though, if I make Millénaire it's first because I enjoy the coding challenge ;) Any good tutorials or docs on best practice for SMP mods somewhere?

 

Especially if you're saying you're gunna drop that whole annoying 'Forge Lite' crap. That is really annoying.. hehe

 

Well, I don't have a choice if I want to do SMP using ForgeMP I guess. And my Forge Lite might be annoying, but I had done polls of my users and something like 15-20% of them can't install Forge due to incompatibility with other mods... I think MP support is worth it and with 1.3 anyway I'm not having much choice, but there is a drawback in terms of compatibility ;)

 

Otherwise, what strategies are you guys using in terms of client/server version compatibility? I tend to release new Millénaire versions quite frequently (these days every week, before often more than that). Obviously for MP requiring the client and server versions to be in sync would be a giant pain for users. I'm thinking of having a "compatibility version" code that would stay the same as long as no change I've made breaks compatibility - for instance new buildings would be server-only, so no problems there, changes to GUIs would generally be client-only, so no problems either, but if I add new blocks or new villager types (with client-side skins) I'll need to break compatibility.

Link to comment
Share on other sites

We determine the mod matching using the mod.toString(), which defaults to getName() + " " + getVersion().

So if you override toString() to only change when you want it to not match.

I was thinking of expanding that to something a bit more complicated (NetworkMod.checkModMatch(String)), but nobody has shown any interest in this particular aspect.

 

As for the issue of your users not using forge because it's compatibility issues, in most cases the mod they wish to use either

1) They arnt installing it correctly.

2) Doesn't really need to edit base classes, and the modder should update to Forge. or

3) Its not really a good mod :P or

4) The modder doesn't care about compatibility.

If you're editing base classes, in your mod, you're honestly doing something wrong.

 

 

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

We determine the mod matching using the mod.toString(), which defaults to getName() + " " + getVersion().

So if you override toString() to only change when you want it to not match.

I was thinking of expanding that to something a bit more complicated (NetworkMod.checkModMatch(String)), but nobody has shown any interest in this particular aspect.

 

Ok, thanks. Then maybe I'll have getVersion() be my "compatibility version code" and then use a separate sub-version code to differentiate intermediate releases.

 

And I like your expended check idea better. It could be implemented with a default method doing exactly what is being done now too, so it wouldn't change anything for anyone not wanting to use it ;)

 

As for the issue of your users not using forge because it's compatibility issues, in most cases the mod they wish to use either 1) Doesn't really need to edit base classes, and the modder should update to Forge. or 2) Its not really a good mod :P or 3) The modder doesn't care about compatibility.

If you're editing base classes, in your mod, you're honestly doing something wrong.

 

My issue is not deciding which mod author is right or wrong in how he is implementing his mod but to try and make Millénaire work for as many people as possible ;) And IIRC, there are modding APIs that are not compatible with Forge right?

 

So otherwise, any tutorial or guidelines I can use?

Link to comment
Share on other sites

Humm, I can't seem to find any proper tutorials beyond this. I am not good at writing tutorials, so I leave it up to other people.

However if you have specific things I can point you in the proper direction.

 

Registering your entities: MinecraftForge.registerEntity

Registering guis: IGuiHandler -> MinecraftForge.registerGuiHandler

Sending keys, you'd have to write your own packet handler, and honestly, you'd prolly wanna do that for a lot of other things, so I suggest looking at IConnectionHandler, IPacketHandler.

 

Like i said, give it a poke and if you get to specific parts, ask.

One thing you really should remember though, is to separate your logic. So that you only do the real logic when you know that you are the definitive source. {AE: you only set blocks, or things when you're the server, or you're on SSP}

 

As for the incompatibilities, for the most part, most major APIs are compatible with Forge. PAPI, GuiAPI, etc... If we are incompatible with certain apis, we can become compatible. And if its really something important, the author can submit a PR to Forge and get his API cleaned up and used by more users.

 

The point of Forge is to be open source and allow for people to submit things, and have them incorporated. Forge strives for more compatibility and ease of use between mods. As well as keeping in development with what modders need to make there mods better and easier for the end user to use.

 

An example of this would be ISoundHandler, which is a interface that lets you deal with sound events. This allows for many things such as accessibility mods, which allows deaf people to see sound cues. Or ease of use for the end user's by allowing modders to add there sounds directly from inside the mod's zip to remove the need for the end user to do anything more then drop the zip into the mods folder.

This required editing the same class that AudioMod edited, so at first, we made it so that things worked properly if someone installed AudioMod alongside Forge, but after more research, found that AudioMod was actually almost completely PaulsCode and improperly attributed. So we incorporated it's opensource parts and gave proper attribution. Therefore giving more credit to the original authors, keeping compatibility, making the install easier for users, and allowing us to have more useful functionality.

 

So ya, I would go to those 15-20% of your users, and ask them exactly which mods/apis are incompatible with Forge. And see if we can resolve the issues.

 

All mods should be solely 'drop this zip in mods folder', and all APIs should strive to be compatible with anything they can and provide unique functionality. I am always willing to have modders come to me and discuss how we can make everything work together.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

FMLCommonHandler.instance().getMinecraftRootDirectory(); Will return either the .minecraft folder on the client, or the folder with the server jar in it on the server.

I would HIGHLY recommend you append  "mods/Millinaire" to that so that you have your data stored in the mods folder. One thing that bugged me about Mill was it sticking things in the root directory, no mod should do that.

ROOT/mods/MODNAME/ should be used for data storage

ROOT/config/MODNAME/ should be used for user configurations.

 

That way the root directory doesn't get cluttered :P

 

As for the world folder, I cant rememebr off the top of my head, but this should work: {note written off top of my head, may not compile}

public File getWorldFolder(World world)
{
  ISaveHandler save = world.getSaveHandler();
  if (world.isRemote) return null; //In SMP no save folder, cuz we arnt server
  return ((SaveHandler)save).getSaveDirectory(); 
}

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

Github.com/cpw/iron chest and github.com/cow/compactsolars

 

I must be making a stupid mistake, having never used Git, but how do I check those out using eGit in Eclipse? I've tried using import > Git then entering http://github.com/cow/compactsolars as the URI but I'm getting a 301 error.

do you mean http://github.com/cpw/compactsolars not http://github.com/cow/compactsolars

Link to comment
Share on other sites

Github.com/cpw/iron chest and github.com/cow/compactsolars

 

Ok, got them and had a look. Very clean code. I liked how you isolated the server and client specific parts so as to have the maximum amount of code being shared. That should help me work out my split. One question though, in practice how do you work on it in Eclipse and to test compilation? It looks like it would only compile and run if you put client+common in a client MCP install, and server+common in a server MCP one. Is that what you do, just moving the changes you make in common to both sides manually?

Link to comment
Share on other sites

In eclipse you can have linked source files, and debugging in eclipse will pull all source files that are linked and compile them.

It only because a issue when you go to reobf, in which case you do exactly what you said,

Make copy of MCP/src to MCP/src-bak

Copy Mod/Client -> MCP/src/minecraft

Copy Mod/Common -> MCP/src/minecraft

Copy Mod/Server -> MCP/src/minecraft_server

Copy Mod/Common -> MCP/src/minecraft_server

Recompile, reobf

Del MCP/src

Move MCP/src-bak -> MCP/src

Small batch file to do that makes it simple.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

Kinniken, in eclipse yes i have two projects: project 1 (client side) depends on the forge-client and has "client" and "common". project 2 depends on forge-server and has "server" and "common". Works very well and is quite robust. Just make sure you check both sides for errors before you do a build push.

 

If you look in my projects you'll see there's an ant build script that can help by pushing all the "manual" work of rebuilding/reobfuscating the code for both client and server. (I also have an unshared version that is tentatively pushing a bukkit build too ;) ).

 

I recommend you start by putting everything in common and then just peeling out enough that client and server compile.

 

I also strongly recommend you use your own packages for your mod. that way you don't clutter up the net.minecraft.src package namespace.

 

Finally, the @SidedProxy is useful (for me) because it lets the mod loader load in the right "sided" class for client or server into my mod. I use that as a proxy to access side specific behaviour without having to code duplication everywhere.

 

 

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.

Announcements




  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • They were already updated, and just to double check I even did a cleanup and fresh update from that same page. I'm quite sure drivers are not the problem here. 
    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
  • Topics

×
×
  • Create New...

Important Information

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