Jump to content

Recommended Posts

Posted

Ok, so I want to use the Cofhlib API, but I have to idea where to actually *put* the API. I am using eclipse and have my mod set up there, so do I just need to extract the API into eclipse? Also I re-set up my dev enviroment when updating my forge, and instead of putting things into a hiearchy, eclipse now lists all packages on the same level and displays them as mod.stuff.morestuff, and all the minecraft packages are the same way, they are all listed as net.minecraft.whatever, which makes it nigh impossible to read or find where things are easily. Sorry for probobly very nooby questions, thanks for all the help.

Posted

In case it is a .jar file just put it in a (new) /libs folder in your forge-src folder and import it as a Library. You should be able to access its classes.

PM's regarding modding questions should belong in the Modder Support sub-forum and won't be answered.

Posted

You are using the cofh api? How are you doing that, I am trying to but I can not find any download for the api, only the whole cofh core, and it downloads as a zip file, and I have trouble importing the zip and adding it to my build path, as it doesnt show any of the source. I succesfully installed the IC2 api as it ships as a jar.  How do I go about getting the correct stuff into my workspace for implementing?

Edit:I figured it out and found a CofhLib Jar. Thanks for everyone thats helped.

Posted

I think people often get confused about what an API is.  I get confused about it too, but here is my understanding (feel free to correct me).

 

Normally after compilation and obfuscation a Java mod's functionality isn't really accessible in a human-readable and accessible way. However, people making a mod can choose to expose functionality as an API by constructing their build (I think you can identify API code in the build.gradle if you're creating an API) such that portions are not obfuscated and can be referenced by their original method name.

 

The trick then is to make your dev environment "know about" this API so that when you use the API methods in your code there isn't any error.  I think there may be two ways -- you can bring the source over but segregate it as required code that doesn't get built into your mod (I think that is what diesieben07 is suggesting above), or you can actually bring the actual mod into your run location so it is accessed similar to how it will be  when you mod is actually published.

 

What you don't want to do is to bring their source code into your mod.  Yes you want Eclipse to recognize the methods from the API, but that should be like other libraries instead of actually part of your code.

 

I don't know all the details to do the above right, but that is the general concept.  You might want to check out CoolAlias' tutorial on APIs: http://www.minecraftforum.net/topic/2496232-tutorial-modding-with-apis/

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

Posted

maby im missing something but all of the mods i have looked at include the apis they use e.g. Extra utills uses the the cofh energy api and the api is included in the extra utills jar.

 

Also not including the api would make your mod dependent on the mod it belongs wouldn't it?

I am the author of Draconic Evolution

Posted

I think people are confusing "using open source code" with "using an API".  If someone writes an "API" but then gives out the open source code for it, you certainly are allowed to use it.  But that is just copying code, not using an API.

 

An API is an agreed upon set of calls between two independently developed pieces of code. 

 

Also not including the api would make your mod dependent on the mod it belongs wouldn't it?

 

That's the whole point.  You want to take advantage of the other developers' effort by depending on it.  Imagine I made a mod that did some cool world generation and had and API called generateCoolWorld().  You would use my mod (required dependency) and call that method.  But I could independently keep improving what that does -- maybe fix bugs, or make it even cooler world.  You could drop in any version of my mod and the API would be there for you -- the API is like a "contract" or standard.  You should never have to re-build your mod because I fixed a bug in my API.  You just update my mod instead.

 

There is nothing wrong with using open source code, but if you're building it then I'm pretty sure it isn't an "API".

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

Posted

If your are including an API because you want a soft-dependency (integration if the mod is present, otherwise just don't integrate) you are doing it wrong. Use the Annotations in the Optional class from FML. They allow you to handle this without including the API code.

 

Yes, I should have mentioned that.  Here is tutorial on @Optional annotation.  http://minalien.com/minecraft-forge-feature-spotlight-optional-annotation/

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

Posted

maby im confused because the redstone flux api isnt specifically designed to allow mods to interact with Thermal Expansion it allows any mod to interact with any other mod using the api even if there are no cofh mods installed.

I guess i will just have to do some research and try to wrap my head around it starting with the links you provided.

 

Edit:

There is nothing wrong with using open source code, but if you're building it then I'm pretty sure it isn't an "API".

What do you mean by "building" I am i am implementing the apis interfaces

 

If your are including an API because you want a soft-dependency (integration if the mod is present, otherwise just don't integrate) you are doing it wrong. Use the Annotations in the Optional class from FML. They allow you to handle this without including the API code.

 

I am using is as the power system for my mod and it dose not in any way dependent on any other mod but it wont function without the api so i am dependent on the api itself not the mod it belongs to.

 

 

 

I am the author of Draconic Evolution

Posted

Ok i must ask is an interface considered an api? because the redstone flux api dosnt contain any methods just a set of interfaces.

 

Edit: i just realized that was a stupid question "Application Programming Interface"

 

This is kinda a complicated question.  As diesieben07 indicates, the word "interface" can mean different things.  In Java it specifically means a set of public unimplemented methods (someday soon Java will support "default" methods in interfaces allowing some implementation) that enforces compliance on those classes that implement it.

 

The Java interfaces are mostly intended for enforcing compliance within an internal development team.  For example, if I had a team of software coders working on something I could define the interfaces for them to implement and then they would go off an implement them and I would be sure that the result would have the methods I expect so I could assign another software developer to write code that calls those interfaces. 

 

There is a secondary use of Java interfaces in helping provide "multiple inheritance".  This is because Java allows you to test instanceof for interfaces.  You can only extend one class, but you can implement multiple interfaces.  So if I wanted to group a bunch of classes that were not extending the same parent class I could define an empty interface and have all the classes implement it and then I could treat them all as instances of that interface.  Not sure if you know what I mean, but I do find this useful sometimes.

 

An API is usually a bit more "external".  It is telling other people how to access the functionality and resources of your code.  But you might have no interaction with those people at all.  You just publish your compiled code and a documented API and they can use it how they want.

 

I'm not entirely sure why someone would put a Java interface in an API.  It is not directly callable because the interface isn't implemented.  It can be used to allow the mod with the API to "discover" and use your classes though.  For example, imagine that there was a mod that wanted to add sea life entities to Minecraft and they wanted to be aware if your mod also has sea life entities.  Then the API could provide a Java interface for sea life, you could implement that interface in your seal life entity classes, and in their mod whenever they tested for instanceof they would also see all your entities (and further know how to access them, through the methods the interface forces you to implement).

 

Not sure if that is entirely clear.  But I would say that generally a Java interface is more about internal developers working together on the same code base, and an API is about external developers being able to interact with your code product.

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

Posted

Ok so i understood most of what you just said and a lot of it i already knew from the java tutorials i have read.

It seems to me from everything you have told me the Redstone flux api isnt like most apis its just a universal energy system that mods can implement in order to be compatible with each other.

I am the author of Draconic Evolution

Posted

Ok so i understood most of what you just said and a lot of it i already knew from the java tutorials i have read.

It seems to me from everything you have told me the Redstone flux api isnt like most apis its just a universal energy system that mods can implement in order to be compatible with each other.

 

Basically if I want my mod to work with yours I can choose to:

1) just say "hey can you make some deobfuscated methods that we agree on?"  No Java interface but just trust you'll implement the methods as agreed.

b) say "I'll expose an deobfuscated API in my obfuscated mod that exposes a Java interface that you can implement (without needing source)"

z) say "Here's source code for a Java interface that I hope you expose as a deobfuscated API in your obfuscated mod."

 

All three methods can work, but are just different perspectives on the same problem.  Sounds like Redstone is taking the third approach.

 

 

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

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.