Jump to content

Recommended Posts

Posted

1.12 and before had "@Optional.Interface" for interacting with other mods without requiring the other mods as dependencies. If the other mod is installed do something, if not, don't do it.

 

Example: https://github.com/MachineMuse/MachineMusePowersuits/blob/1.12.2-experimental/src/main/java/net/machinemuse/powersuits/item/tool/ItemPowerFist.java#L64-L74

 

1.13 & 1.14 don't have the Optional.Interface thing. Does it have something else instead and if so what is it?

 

Is there a way in >=1.13 to do what the Optional.Interface for <=1.12 did, and if so, what is it?

Posted

Well, the problem is, and I'm directly quoting the guy working on the mod:

Quote

[T]here is no way to conditionally register items. And that's just it, every addon MPS implements, except power, is based on another mod's item.

 

Posted
32 minutes ago, eyeonus said:

Well, the problem is, and I'm directly quoting the guy working on the mod:

He could always check if the item exists by looking at the registry.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
44 minutes ago, eyeonus said:

Pretty sure the doesn't exist at pre-load, and IIRC, that's when items need to be registered.

4 hours ago, eyeonus said:

[T]here is no way to conditionally register items.

Register the item always. He said it himself. Do the functionality only when the item exists. You can obtain the Item as an object then use it's onItemUse/onItemRightClick method to do it's functionality.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
1 minute ago, diesieben07 said:

You need to code your item class in a way that is not dependent on the other mod.

Quote

[E]very addon MPS implements, except power, is based on another mod's item.

 

Posted
22 minutes ago, eyeonus said:

[E]very addon MPS implements, except power, is based on another mod's item.

It looks like you are quoting him from somewhere I'm not sure if I should be talking to him the mod dev or to you about this issue. I've provided a means to get around the problem, and all you have done is say no that wont work. Why wont it work? Where does it fail at? Have you tried this at all? Are you a mod developer?

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

It means it's not possible to make the item not depend on another mod.

 

For example, one of the items in the 1.12 version is a module that adds the IC2 leaf blower as an installable module in MPS' Power Fist, meaning that the Power Fist can act as the Leaf Blower.

 

The Leaf Blower module depends on IC2. It can't exist without IC2 also being installed.

Posted
6 minutes ago, Animefan8888 said:

This isnt true at all.

It is 100% completely true. The code that makes the leaves be blown is in IC2, not MPS. The MPS module uses the same item image as the IC2 blower. EVERY module in MPS is just an interface to the actual item from the mod it's dependent on. The module can't exist without the mod it is dependent on because the module doesn't have any code to do the thing.

 

The leaf blower module uses the code in IC2 to blow leaves.

The One Probe module uses the code in TheOneProbe to do the probing.

The oxygen tank module uses the code from GalactiCraft to store and use Oxygen.

Posted (edited)

You told me what. Not how.

 

If you can point to a tutorial or reference library or something that explains how, that's fine. I don't need my hand held.

 

But when you say soft dependency, the only way to do a soft dependency that I know how to do is the optional interface thing that doesn't exist anymore.

 

And is a soft dependency soft in dev too, or is it still a hard dependency in a dev environment like it was back when optional interfaces was a thing that existed?

Edited by eyeonus
Posted

Okay, so final question:

 

When I'm testing the code in a dev environment, would I need to have the mods such items depend on installed?

 

In other words, if I'm working on the code for an item that depends on ModA, but I also have another item that depends on ModB, which I'm not working on, do I still need to have ModB installed in my dev environment to run the dev build?

Posted
7 minutes ago, diesieben07 said:

Small example (pseudocode):

I feel like this way of doing it is overboard. Here is how I would do it; under the following assumptions.
 

I assume any and all modules interact with the player in some way. Most likely from some sort of right click action. IE Item#onItemUse or Item#onItemRightClick or some method within the Item class.

I assume that it also applies no modifier to the feature of the Item in anyway, aka it works exactly like the Item in all use cases.


Therefore wouldn't the Item itself work as a "module".

Thus...

class PowerFistItem extends Item {
  
  onItemUse(ItemUseContext context) {
    // Maybe no for loop just access the active Module Item?
    for (Item item : heldStack.getCapability(PowerFistCapability.CAPABILITY).orElseThrow(IllegalStateException::new).getModuleItems()) {
      result = item.onItemUse(context); // Maybe you'll have to construct your own ItemUseContext based on the ModuleItem...
      if (result != FAIL) return result;
  

 

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted

For clarification, the "module" is the thing in MPS that depends on something from another mod to do whatever it does.

The "item" is the thing in the other mod.

 

So, the leaf blower module is a bit of code that references the leaf blower item in IC2.

 

The module doesn't do anything on its own. It's just an interface to the item.

 

Registered or not, it needs to not show in game if the mod it depends on isn't installed, because it's literally just a useless waste of space in that case. But disabling an item isn't the issue.

Posted
7 minutes ago, eyeonus said:

Registered or not, it needs to not show in game if the mod it depends on isn't installed,

Which it won't because the Item is never added to the registry...

7 minutes ago, eyeonus said:

The module doesn't do anything on its own. It's just an interface to the item. 

Good? Then why is the module needed in the first place? Why not just use the Item itself?

10 minutes ago, eyeonus said:

So, the leaf blower module is a bit of code that references the leaf blower item in IC2.

Why not get rid of the thing that goes inbetween? If Module#doUseAction just calls Item#onItemUse and Module#doRighClickAction just calls Item#onItemRightClick what is the point?

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
5 minutes ago, Animefan8888 said:

Which it won't because the Item is never added to the registry...

Good? Then why is the module needed in the first place? Why not just use the Item itself?

Why not get rid of the thing that goes inbetween? If Module#doUseAction just calls Item#onItemUse and Module#doRighClickAction just calls Item#onItemRightClick what is the point?

Except, according to lehjr, the module has to registered before we can check if the other mod is installed.

The module isn't used directly. The module is installed into the Power Fist item, the Power Fist is what the player is using. (Install leaf blower module into Fist, select leaf blower as active module, right-click of Fist now makes leaves blow. Select other module as active, now right-click activates that module instead.)

The point is being able to have multiple modules that can be cycled through so that one item - the power fist-  can do the same thing as many items from many mods.

Posted

To answer your question, no, I'm not a mod developer per se. I am a "contributor", in that I help out lehjr with development on MPS from time to time, which does include writing code for the mod.

Posted
6 minutes ago, eyeonus said:

Except, according to lehjr, the module has to registered before we can check if the other mod is installed.

Why is that? The module isn't actually used until you arrive in game does it?

 

7 minutes ago, eyeonus said:

The point is being able to have multiple modules that can be cycled through so that one item - the power fist-  can do the same thing as many items from many mods.

Ok here this out. I have a NonNullList<Item> this list contains all of the Items from the mods I want to implement into one Item; the Multi-Tool. I can now have an int that represents what Item it currently has active. Which can be changed via a hotkey/keybinding. Now the Multi-Tool just needs to access that List with the index of the active setting. Then call Item#onItemUse on the Item in the NonNullList<Item> no need for modules. Now how did I get this NonNullList<Item> for my Multi-Tool?

 

I used an Event that fires after all Mods have added their Items to the registry(I assume that FMLLoadCompleteEvent is fired after all mods are done; though it does say mods shouldn't use it). Then I access the Item registry with ForgeRegistries.ITEM.getValue(...) and pass in the Items registry name to see if it is there. If it isn't there I don't add it to my list. Boom I have a List of Items that my item can now use, and they are from other mods.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
19 minutes ago, Animefan8888 said:

Why is that? The module isn't actually used until you arrive in game does it?

 

Ok here this out. I have a NonNullList<Item> this list contains all of the Items from the mods I want to implement into one Item; the Multi-Tool. I can now have an int that represents what Item it currently has active. Which can be changed via a hotkey/keybinding. Now the Multi-Tool just needs to access that List with the index of the active setting. Then call Item#onItemUse on the Item in the NonNullList<Item> no need for modules. Now how did I get this NonNullList<Item> for my Multi-Tool?

 

I used an Event that fires after all Mods have added their Items to the registry(I assume that FMLLoadCompleteEvent is fired after all mods are done; though it does say mods shouldn't use it). Then I access the Item registry with ForgeRegistries.ITEM.getValue(...) and pass in the Items registry name to see if it is there. If it isn't there I don't add it to my list. Boom I have a List of Items that my item can now use, and they are from other mods.

No, but it needs to be REGISTERED during init, because the modules, which are not items in the sense that they have any direct functionality, are items in the sense that they are things you can craft and put into your inventory.

 

The problem is that most items can't have their functionality called indirectly. That's why the Morph-O-Tool literally transforms into whatever item you're wanting to use. You can't say tell the other mod's code "Hey, pretend this thing which isn't your item actually is and do the thing that item does." You can't pass an ItemStack of the actual item the module is pretending to be, in other words.

 

Posted
8 minutes ago, eyeonus said:

You can't pass an ItemStack of the actual item the module is pretending to be, in other words.

Then don't. Pass an ItemStack that has the Item it talks about. Trick the system. That's how a lot of Right Clicking blocks work. They use a FakePlayer. I know for a fact that some Items in their Item#onItemUse and Item#onItemRightClick won't even care. Such as the BuildCraft Wrench won't even care I'm pretty sure the Thermal Expansion one won't after several minutes searching.

10 minutes ago, eyeonus said:

No, but it needs to be REGISTERED during init, because the modules, which are not items in the sense that they have any direct functionality, are items in the sense that they are things you can craft and put into your inventory.

It's your/his system. You get to choose where and when things can be registered. Also why limit that in the first place? I know why forge does it; if it didn't all types of things would go wrong. People would register things conditionally and they would be different on the server vs the client. But your modules don't technically even need to be on the client, other than to display information such as which module is active. Which I assume it is told "hey this is the active module" every time the module changes/becomes un-synced.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted (edited)

As I just said, you CAN'T. You can't pass an ItemStack AT ALL. That's the problem. The right-click method doesn't have an ItemStack parameter.

 

Items have to be registered during init. If you don't register them during init, they can't be registered later. Anything with a crafting recipe has to be registered. The registration has to be during the initialization phase.

Edited by eyeonus
Posted
5 minutes ago, eyeonus said:

Items have to be registered during init.

I don't think you understood what I said. I never said anything about registering Items. Plus what is init that's an old term used pre 1.13. FMLPreInitializationEvent, FMLInitializationEvent, and FMLPostInitializationEvent are gone.

 

7 minutes ago, eyeonus said:

You can't pass a ItemStack AT ALL.

Yes you can...all an ItemStack is is an Item with entry specific values like a count and Capabilities.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Posted
36 minutes ago, eyeonus said:

As I just said, you CAN'T. You can't pass an ItemStack AT ALL. That's the problem. The right-click method doesn't have an ItemStack parameter.

You haven't explained why you can't pass an ItemStack but can pass an Item. Is it because this other mod requires an item be passed because that's the method signature? Already you're in dependency territory, that stuff lives inside the `doStuff` implementation D7 talked about. Everything outside of `doStuff` doesn't know about the method that only accepts an Item.

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.