Jump to content

[How-To]Build multiple separate projects with Gradle


Recommended Posts

Posted

This post is meant to help those not accustomed to building with Gradle, but wanting to use separate directories for making mods. (I think some people name it "Pahimar setup" or something...)

As each setup can be different, I will take mine as a reference (the "Goto setup" :P), and explain it as simply as possible.

 

Before beginning

This tutorial is meant to be IDE independent, and as such, use "conventional" naming of things and doesn't describe IDE settings step. Those you should know how to do, since you are supposed to choose your IDE while learning to code.

 

For example, a "Project" is a group of resources, eventually with dependencies, that can be run. Eclipse uses this term, while IntellijIdea uses "Module". Not to be confused with IntellijIdea "Project" (which can be a group of projects) nor Gradle "Project", which are things that can be "built" through Gradle.

 

I personally go with one "Project" = one mod = one Gradle "Project". (because Forge recommended it this way, and it makes sense too)

 

The "dependency" setup

This setup is based on dependencies, so build files are simplified and easier to change.

 

My directories are as follows:

-Forge (the folder inside which forge source has been extracted, per the main tutorial)

\build.gradle

\settings.gradle

-Project1 (another folder, which contains the mod1)

\build.gradle

-Project2 (another folder, which contains the mod2)

etc.

 

Note the new file, settings.gradle, which only contain:

includeFlat 'Project1','Project2'

This basically specify that "Project1" and "Project2" folders depend on the Forge folder. For example you code a main core API in the Forge source, and dependent mods in the other folders. You can add more to the list.

Specific subfolders can be added with line such as 'Project/subfolder'.

You can make it a bit more intelligent with code for folder look-up, but this is outside of my post scope.

 

build.gradle in Forge folder is a modified version of the file shipped with Forge sources:

[spoiler=For 1.6.4]

buildscript {
    repositories {
        mavenCentral()
        maven {
            name = "forge"
            url = "http://files.minecraftforge.net/maven"
        }
    }
    dependencies {
        classpath 'net.minecraftforge.gradle:ForgeGradle:1.0-SNAPSHOT'
    }
}
allprojects {
    apply plugin: 'forge'
    minecraft{version = "1.6.4-9.11.1.964"}
    version = "1.0"
    archivesBaseName = project.projectDir.name
}

 

 

[spoiler=For 1.7.2]

buildscript {
    repositories {
        mavenCentral()
        maven {
            name = "forge"
            url = "http://files.minecraftforge.net/maven"
        }maven {
            name = "sonatype"
            url = "https://oss.sonatype.org/content/repositories/snapshots/"
        }
    }
    dependencies {
        classpath 'net.minecraftforge.gradle:ForgeGradle:1.1-SNAPSHOT'
    }
}
allprojects {
    apply plugin: 'forge'
    minecraft{version = "1.7.2-10.12.0.985"}
    version = "1.0"
    archivesBaseName = project.projectDir.name
}

 

 

It adds a body to "allprojects" with basic settings, such as applying forge, settings minecraft version and a general name for the mod jar. (

archivesBaseName

) This body applies parameters to all projects, including the Forge one.

Use "subprojects" to work on all projects except the Forge one.

 

Let see how it simplify the mod build.gradle, for example the Project1/build.gradle:

version = "1.1"
sourceSets.main{
    java{
srcDirs project.projectDir.getPath() exclude ("bin/**", "build*")
}
    resources{
srcDirs project.projectDir.getPath() exclude ("bin/**", "build*")
}
}
processResources {
    // 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'
    }
}

The first body is made to set the mod source differently. With this, the "Project1" folder contains directly the source package, without "src/main/" intermediate folders, and making sure all superfluous files are excluded (here, a "bin" folder, and any file or folder whose name begin with "build").

Project1
\assets\modid1\textures\...
\mods\modid1\...

Of course, this entire file is optional and highly dependent on your own setup.

Note that

project.projectDir

reference the folder as File, for easy copy-pasting in another mod folder.

 

Now we can test the build with

gradlew build

by command line in Forge folder.

 

Or with the Gradle plugin in Eclipse, open the gradle view and launch the "build" task for the Forge imported Gradle project.

 

You should now have a simple jar into each Project/build/libs :)

 

 

The "Independent" setup

Again, you have multiple mods in separate folders, but don't want to use the Forge folder, nor do you want to build all mods at the same time.

Indeed, you don't need to.

Per the main tutorial, you made a Forge project, ran with either

gradlew setupDevWorkspace

or

gradlew setupDecompWorkspace

ForgeGradle and its dependencies should now be cached.

 

Copy over the build.gradle file from the Forge folder in all your mods roots. (plus the gradle folder and gradlew files if you don't want to install Gradle)

You can now delete the Forge project folder.

 

With this project structure:

Project2
\resources\assets\modid\textures\...
\src\mods\modid\...
\build.gradle

 

A valid build.gradle file is:

[spoiler=For 1.6.4]

buildscript {
    repositories {
        mavenCentral()
        maven {
            name = "forge"
            url = "http://files.minecraftforge.net/maven"
        }
    }
    dependencies {
        classpath 'net.minecraftforge.gradle:ForgeGradle:1.0-SNAPSHOT'
    }
}
apply plugin: 'forge'
minecraft{version = "1.6.4-9.11.1.964"}
version = "1.0"//Set the mod version, is appended to the end of the jar name
archivesBaseName = project.projectDir.name// Set the jar name as the project root folder name
//Optional: change the project structure
sourceSets.main{
    java{
srcDirs 'src'//set the source folder as the /src subfolder
}
    resources{
srcDirs 'resources'//set the resources folder as the /resources subfolder
}
}
processResources {
    // 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'
    }
}

 

 

[spoiler=For 1.7.2]

buildscript {
    repositories {
        mavenCentral()
        maven {
            name = "forge"
            url = "http://files.minecraftforge.net/maven"
        }maven {
            name = "sonatype"
            url = "https://oss.sonatype.org/content/repositories/snapshots/"
        }
    }
    dependencies {
        classpath 'net.minecraftforge.gradle:ForgeGradle:1.1-SNAPSHOT'
    }
}
apply plugin: 'forge'
minecraft{version = "1.7.2-10.12.0.985"}
version = "1.0"//Set the mod version, is appended to the end of the jar name
archivesBaseName = project.projectDir.name// Set the jar name as the project root folder name
//Optional: change the project structure
sourceSets.main{
    java{
srcDirs 'src'//set the source folder as the /src subfolder
}
    resources{
srcDirs 'resources'//set the resources folder as the /resources subfolder
}
}
processResources {
    // 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'
    }
}

 

 

 

You can now import the mod project in your favourite IDE , with the build.gradle file.

 

You can also run

gradlew build

by command line in a project folder, to get the corresponding mod jar in its build/libs subfolder. :)

Posted

Thanks for your guide. I begin to understand what gradle is being used for (or atleast whats the intention :) )

 

People call this setup "Pahimar-Setup", because Pahimar (Youtube Channel) introduced some tutorials on how to setup eclipse to include each mod as a separate project.

 

Now I'm looking for on how to teach IntelliJ to load my sub-modules as separate mods.

Posted

Yeah, this is the nice part of Gradle for us modders, looks at lot better than Ant script IMO :)

And don't forget the automated forge updates.

 

Ok, fixed Pahimar name :P

 

I think IntelliJ can import Gradle projects if you point it the build.gradle file.

You might have to change the run configuration on your own though.

Posted

Use

include

to work with Projects folder inside the Forge one. (hierarchical type)

includeFlat

works for folder on the same level. (flat type, ie. Forge and Project1 have the same root folder)

Posted

Thank you for that clarification. Is there any way to include the Project1 and Project2 outlined in the code block?

Development
    Forge
        the stuff normally in the forge dir
    src
        Project1
            Project1 Stuff
        Project2
            Project2 Stuff

Posted

Aboout this piece of code:

sourceSets.main{
    java{
srcDirs project.projectDir.getPath() exclude ("bin/", "build*")
}
    resources{
srcDirs project.projectDir.getPath() exclude ("bin/", "build*")
}
}
version = "1.1"

is that code in the build.gradle in the forge folder, or is is it the build.gradle in the "Project1" folder?

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted

Could you please update the main post so it fits the 1.7 upgrade because a lot of stuff changed in 1.7 so there's a new gradle version?

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted

I have to admit that I could only get this to work once... there is something I am missing.

 

I have added the allprojects section to build.gradle (as listed in the OP), and I can successfully build the project with no errors, but this is only as long as there is no settings.gradle file with includeFlat 'someproject' (as in it only builds the main project)

 

as soon as i try to add a project to settings.gradle I get this error:

 

* Where:
Build file 'C:\Users\tenowg\Desktop\Forge\EclipseTest\build.gradle' line: 19

* What went wrong:
A problem occurred evaluating root project 'EclipseTest'.
> java.lang.NullPointerException (no error message)

 

EclipseTest is the main test project, I have tried the following:

 

  • Creating a full project as the subproject (and rewriting the build.gradle for the subproject)
  • Creating a empty project with just the build.gradle (and without)
  • Letting it create the folders
  • beating my head on the keyboard

 

This is under 1.7.2.... using all builds I could find.

 

I have tried all this in IntelliJ and Eclipse

 

The error line is always on the "apply plugin: forge" in build.gradle of the main project.

 

Maybe a complete "noob" step by step version?

 

Thanks again, and I do know this works, as it has worked once, but I can't seem to replicate it...

 

 

Posted

At the independent setup, you said that you need to setup your forge folder with either "gradlew setupDecompWorkspace" or "gradlew setupDevWorkspace". Do you also need to run "gradlew eclipse" to make it work, cause i did everything you said in the post, but if i import a existing project into workspace, it can't find my project.

 

PS: i didn't use the gradle plugin for eclipse because it seems like i don't have the eclipse marketplace...

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted

I have to admit that I could only get this to work once... there is something I am missing.

 

I have added the allprojects section to build.gradle (as listed in the OP), and I can successfully build the project with no errors, but this is only as long as there is no settings.gradle file with includeFlat 'someproject' (as in it only builds the main project)

So your setup should be like:

Forge
\EclipseTest
->build.gradle
->settings.gradle
\someproject
->build.gradle (optional)

 

Make sure the 'allprojects" body is between the "buildscript" and the "processResources" bodies.

Try to

gradlew clean cleanEclipse cleanIdea

once before next attemp. Old build attempts could screw things.

 

You can have a try with the "Independent" setup.

I'd recommend using Eclipse with Gradle plugin to import as a Gradle Project.

Then run

gradlew clean setupDecompWorkspace eclipse

It is less clumsy that IntelliJ, IMHO.

 

@larsgerrits

Running the Forge gradlew things is only needed once, to cache the libraries. The "eclipse" task is not needed here, AFAIK, because you are not using the Forge folder to import into Eclipse.

The "independent" setup only needs a valid build.gradle file inside your project (not forge, the mod one).

Then, either import your project (not forge, the mod one) with the Gradle plugin, or, run

gradlew clean setupDecompWorkspace eclipse

at your project, then import it.

  • 3 weeks later...
Posted

Thanks, this really helps me understand gradle abit. I'm trying to set it up so that my separate mods are source folders, and to build them separately. To test I copied the example mod and source folder and changed the names over to "test" (instead of example). I used the 1.7.4 build.gradle code from the Independent Setup, and changed the srcDirs to 'src/test'. When I build and copy the jar to minecraft, under the mods menu I get both the original example mod and my copied test mod. How can I set it up so that it excludes any other source folders in eclipse and builds a specific mod? It would be easier than moving the mods source folder out of the full directory itself, build, then replace the source folder again. Would be very tedious with more than one mod.

 

Heres a screenshot if I don't make sense (really tired while writing this):

 

http://s28.postimg.org/tc4c6a5jx/forge_help.png

 

Red and Green are separate mods and the Blue is what I changed in build.gradle

Posted

@dev909

You didn't follow my instructions for the "Independent setup" here.

I see two mods in the same project folder, and the forge license, readme files...bad boy :P

 

The problem you might not see, is that Gradle sets by default a test folder as src/test/java and src/test/resources, but this is for testing purposes and not supposed to be built with the 'main' sources. This probably conflicts with what you set into the build.gradle file.

 

If you don't want to move out of the Forge folder, at least make a build.gradle file per mod. That is the easiest way to go.

In your situation, put them into the "main" and "test" subfolders with:

sourceSets.main{
    java{
srcDirs 'java'
}
    resources{
srcDirs 'resources'
}
}

  • 1 month later...
Posted

This looks complicated at a first glance. So now we have to learn Groovy if we want to understand what gradle does and how to configure it? And where I can see what all those tasks do exactly (source)?

Posted

I don't think the "Independent" setup requires any groovy knowledge.

That is the default setup that forge invites you to use.

Obviously, the further you go from the default, the more you'll need to understand and change.

 

I only needed to refer to the gradle docs to make this tutorial.

  • 5 weeks later...
Posted

I get an error when importing a gradle project with the independent setup:

 

 

VC9dch1.png

 

 

This is my build.gradle:

 

 

buildscript {
    repositories {
        mavenCentral()
        maven {
            name = "forge"
            url = "http://files.minecraftforge.net/maven"
        }maven {
            name = "sonatype"
            url = "https://oss.sonatype.org/content/repositories/snapshots/"
        }
    }
    dependencies {
        classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
    }
}
apply plugin: 'forge'
minecraft{version = "1.7.2-10.12.0.1056"}
version = "1.7.2-v0.01"
archivesBaseName = project.projectDir.name
sourceSets.main{
    java{
srcDirs 'src'
}
    resources{
srcDirs 'resources'
}
}
processResources {
    from(sourceSets.main.resources.srcDirs) {
        include 'mcmod.info'
        expand 'version':project.version, 'mcversion':project.minecraft.version
    }
    from(sourceSets.main.resources.srcDirs) {
        exclude 'mcmod.info'
    }
}

 

 

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted

Eclipse tells you to "Build Model" before.

I'd advise you to tick the "Run before" box, and add "setupDevWorkspace" to the command, between "cleanEclipse" and "eclipse".

Posted

I ticked the "Run before" box, and changed that line next to it to "cleanEclipse setupDevWorkspace eclipse", but i got the same error.

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted

I searched over the internet, but i couldn't find a solution. Can you help me with this or are you out of ideas too?

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

  • 3 months later...
Posted

Mine won't build.

 

* What went wrong:

A problem occurred evaluating project ':Project1'.

> Could not find method processResources() for arguments [build_60m7ce4rho9j76mu

eei15hel03$_run_closure2@1698f66] on project ':Project1'.

  • 4 months later...
Posted

Having built a chunk of related but separate mods, I was keeping all the files in the same /src/main directory mostly because of not knowing what else to do, but given that I'd like to build them as separate jar files, I ended up here.

 

Good news: I got it to compile.

Bad news: it shoved them all into one jar anyway (which has a clever file name of "Forge 1180.jar")

 

Umm...what didn't I do correctly?

 

Unrelated, I should update Forge at some point, heh.

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

×
×
  • Create New...

Important Information

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