Issues with minecraft forge packages in 1.16.5 - java

I am making a mod in minecraft 1.16.5 forge
I have a tile entity that is used for crafting but I don't want it to craft things every tick.
To achieve this I added a button that sends a package to the server whenever it needs to do the crafting.
I have no idea what I am doing wrong at this point and I cannot find the cause of the issue in the minecraft code because the exception stack does not reference any of my classes.
I am relatively new to minecraft modding and java in general which also isn't very helpful. However I have done my homework and have enough knowledge to know what I actually am doing and not just blindly copy pasting code from tutorials so calling me out to learn java will not help me in any capacity.
I am stuck with this problem for about a week now and this is the last place I can think of that can help me
It works flawlessly in singleplayer but whenever I try to join a server with this mod installed I get an error message on my screen saying
Internal Exception: io.netty.handler.codec.DecoderException: io.netty.handler.codec.EncoderException: java.io.UTFDataFormatExcpetion: malformed input around byte 5
Inside Debug.log it says
[25Nov2021 20:17:50.906] [Render thread/FATAL] [net.minecraft.util.concurrent.ThreadTaskExecutor/]: Error executing task on Client
java.util.NoSuchElementException: packet_handler
I have compared my way of making the packets with multiple mods I found on curseforge most are the same way as I do it.
I have asked around in multiple forge and modding related discord servers but no one was able to help me with my problem.
All tutorials on youtube did the same as I did.
My PacketHandler class looks like this:
public static final String PROTOCOL_VERSION = "1";
public static SimpleChannel CHANNEL;
public static void init() {
int index =0;
CHANNEL = NetworkRegistry.ChannelBuilder
.named(new ResourceLocation("pepsimc","simple_network"))
.clientAcceptedVersions(PROTOCOL_VERSION::equals)
.serverAcceptedVersions(PROTOCOL_VERSION::equals)
.networkProtocolVersion(()->PROTOCOL_VERSION)
.simpleChannel();
CHANNEL.messageBuilder(ProcessingCraftPacket.class, index++, NetworkDirection.PLAY_TO_SERVER)
.encoder(ProcessingCraftPacket::encode)
.decoder(ProcessingCraftPacket::new)
.consumer(ProcessingCraftPacket::handle)
.add();
}
My packet class looks like this:
public final BlockPos Pos;
public ProcessingCraftPacket(BlockPos Pos) {
this.Pos = Pos;
}
public ProcessingCraftPacket(PacketBuffer buffer) {
this(buffer.readBlockPos());
}
public void encode(PacketBuffer buffer) {
buffer.writeBlockPos(this.Pos);
}
public static void handle(ProcessingCraftPacket message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(()->{
final TileEntity TE = ctx.get().getSender().level.getBlockEntity(message.Pos);
if(TE instanceof ProcessingTile) {
final ProcessingTile PT = (ProcessingTile) TE;
PT.process(ctx.get().getSender().level);
}
});
ctx.get().setPacketHandled(true);
}
Thanks alot in advance.

I'm not entirely sure what is going wrong in your code, but since you've asked this in official channels as well without finding an answer, I'm going to refer you to one of my projects with a working custom network packet setup. I'm noticing differences in how we construct the channel and register custom packets, so maybe there's a problem there.
Shared network manager (shared means that it is used on the client and server)
Client packet handler
Server packet handler
Shared packets

I found out what I was doing wrong.
Apparently it had nothing to do with my packets but with my custom recipe type.
I didn't read everything from the buffer which was causing the issue.

Related

How to receive data from a python ZeroMQ PUB server on a Java SUB client (ZMQ)

I'm working with Pupil Labs, a huge open source for eye/pupil tracking. The entire code is written in Python. The so-called Pupil Remote is based on ZeroMQ.
If I start running the Filter Messages everything is fine. For my purposes I need to "translate" Filter Messages into Java because I created an Android app, which should call a client, which has the purpose to serve as the python client.
Here's what I've done so far:
import android.annotation.SuppressLint;
import org.zeromq.ZMQ;
import java.nio.charset.Charset;
import static java.lang.Thread.sleep;
public class ZeroMQClient {
#SuppressLint("NewApi")
public static void requestGazeData() {
ZMQ.Context context = ZMQ.context(1);
ZMQ.Socket subscriber = context.socket(ZMQ.SUB);
System.out.println("Connecting to server...");
subscriber.connect("tcp://xxx.x.x.x:50020");
System.out.println("Connected");
String gaze = "gaze";
subscriber.subscribe(gaze.getBytes(Charset.forName("UTF-8")));
while (true) {
String msg = subscriber.recvStr();
System.out.println(msg);
subscriber.close();
context.term();
}
}
}
Now as you can expect, why I'm asking you, nothing happens, I don't receive any data from the Pupil Labs server. I oriented myself on this post, but unfortunately, it didn't work out for me. Also the IP-Address and port are the same as on the server. It works neither locally nor remotely.
Happy about any answer, since I stuck at this.
Due to the correct establishment in terms of my implementation the actual issue was the firewall, which just blocked the connection. By posting my solution I'm hopefully able to help future visitors of this question.
The final solution, after having debugged the root-cause issue is below
Happy about having answer, you have to set a subscription Policy:
ZeroMQ expects each SUB-side to first explicitly say, what this SUB-side wants to receive from PUB ( Yes, what it to subscribes to ).
Like your mailbox will never get newspapers in, without first subscribing to any. :o)
So setup an empty string "" in the subscriber and you are done:
// String filterPermitANY = ""; // WAS AN EXAMPLE TO TEST
// subscriber.subscribe( filterPermitANY.getBytes() );// IF PUB.send()-s ANY
String gaze = "gaze"; // WAS ON TOPIC
subscriber.subscribe( gaze.getBytes() ); //
Voilá.
Having zero-warranty what python version is running on the opposite side, tweaking may take place for string-representation matching...
( Also recommended to setup LINGER to 1, that prevents from hanging terminations
and preferably it is the best time to turn the process
into using a non-blocking .poll() + .recv( ..., ZMQ_DONTWAIT ) in a soft-realtime maintained event-loop )
[ 1 ] We have got confirmed the Android/ZeroMQ side is working fine
if the PUB-side was mocked by a plain python-PUB infinite-sender and the Android-SUB was subscribed to String filterPermitANY ="";
This makes the above claim "It's an issue from the android side" actually void if not misleading.
[ 2 ] Next comes the question why it still does not work?
And the answer is: because the above designed code does not follow the published principles, how to connect and use the Pupil Labs API.
A careful reader will notice that the Pupil Labs API is not connected by the SUB-side ( be it an Android or python or whatever else implementation of such a peer ) on a port :50020, but on another port, which is first asked about via another dialogue, held over an REQ/REP-formal communication archetype ( lines 13/14/15+19 ).
Epilogue
Knocking on a wrong door will never make the intended interview happen.
One first has to ask onto which door to knock next, so as to get the Pupil Labs API into the game.

Handle multiple clients with one server

I try to get a connection to multiple clients using the Sockets in Java. Everything seems to work, but the problem is, that the server just listens to the first client. If there are multiple clients, the server can send them all messages, but he can just listen to the messages that came from the first client. I tried this all out (I'm at this problem since yesterday). So I'm pretty sure, that the fault has to be in the class "ClientListener".
Explanation:
There is a List with clients (connection to communicate with Strings). In the GUI there is a list, where I can choose, with which client I'd like to communicate. If I change the client, the variable currentClient (int) switches to another number
networkClients is an ArrayList, where all the different connections are "stored".
The first connected client is exactly the same as the other clients, there is nothing special about him. He is called, when the variable currentClient is set to 0 (per default). The variable-switching is working. Like I said, all the clients give me a response if I send them an order, but just networkClients.get(0) is heard by the server (ClientListener).
class ClientListener implements Runnable {
String request;
#Override
public void run() {
try {
while (networkClients.size() < 1) {
Thread.sleep(1000);
}
//***I'm pretty sure, that the problem is in this line
while ((request = networkClients.get(currentClient).getCommunicationReader().readLine()) != null) {
//***
myFileList.add(new MyFile(request));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
I hope someone can help me. I tried many things, but nothing worked.
EDIT: Like I wrote in the code example, is it possible that the while-loop isn't able to switch the number of "currentClient" (which is handled by another Thread)? I tested/simulated something similar in a testclass and the result was, that a while-loop of course can can update the state in it (meaning, that if a variable changes in the () of a while loop, it will of course be checked after every repeat).
You should take a look at multithreading.
Your server program should be made out of:
- The main thread
- A thread that handles new connections.
(Upon creating a new connection, start a new thread and pass the connection on to that thread)
- A thread for each connected client, listening to the each client separately
Take a look at some examples like: (1) (2)
I found the solution:
The Thread sits in the declared method I mentioned in the starting post (in the code snippet) and waits unlimited time for a new response of the client.
So changing the index of the list "networkClients" won't do anything, because nothing will happen there, until there is a new order sent by the client (which lets the thread go further).
So you need to implement an extra listener for each client.

jNetPcap sendPacket() function duplicating the frame

I would like to ask you a specific question: I'm trying to develop a software switch with the jNetPcap 1.4 library on Java 1.7, the goal is to have a program, that can forward packets received on port no. 1 to port no. 2 and vice versa (just on these two NIC-s).
I can see all the incoming packets on both of the interfaces, but when it comes to forwarding, I have a problem: if I send a packet on interface X with pcap.sendPacket(PcapPacket) the nextPacket() function inside the PcapPacketHandler() class will see it also, and will treat is a "new" packet, insted of just ignoring it, because it was sent by the same Pcap instance.
Is there any way to ignore the packets, that were sent by the pcap.sendPacket(PcapPacket) function (so they do not appear again in the nextPacket() function)?
I don't know much about the underlying winpcap library, but I'm sure SharpPcap in C# has this type of functionality. Doesn't jNetPcap have it also, or am I missing something?
Things I've tried:
Using pcap.inject() instead of pcap.sendPacket(), but my NIC doesn't
seem to support this function
Setting the capture direction to inbound only with
pcap.setDirection(Direction.IN) - this seems to have absolutely no
effect, the packets are captured just as before setting it.
Ps. unfortunately I have to write it in Java, if the jNetPcap library does not have this functionality, please, could you advise how to solve the problem? I'm thinking of buffering the sent packets to an array of some type and checking every newly detected packet to be the same as one packet in the array - but this seems to be a computationally complex solution.
Here's my sample code (not the whole, just the relevant pieces):
// Init
Pcap pcap = Pcap.openLive(devices.get(0).getName(), 64*1024, Pcap.MODE_PROMISCUOUS, 1000, errbuf);
...
PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {
public void nextPacket(PcapPacket packet, String user) {
// The duplicate packet that is sent in the sendAll() function also appears here
// Process the packet and add it to the forwarding buffer if needed
buffer.addPacket(packet);
}
}
// This is called in a separate thread, if some packets were added to the buffer
public void sendAll(){
while(buffer.hasNext() != 0){
pcap.sendPacket(buffer.getNextPacket());
}
}
Same goes for the second interface.
Thank you for your help in advance.
I realize this is an old and maybe not so popular topic, but I finally solved this by adding a buffer and constantly checking for duplicates. Since the code is complex, I decided to post the key functionality and how do I ignore the frame based on jnetpcap.com recommendation.
The code:
// we're inside the nextPacket(PcapPacket currentPacket, String user) method
buffer.lock();
for(int j = 0; j<buffer.size(); j++){
if(currentPacket.getCaptureHeader().caplen() == buffer.get(j).getCaptureHeader().caplen()
&& packet.size() == buffer.get(j).size()){
buffer.erasePacket(j);
return;
}
}
buffer.unlock();
// continue packet processing
Feel free to use it in your project.

Apache Camel, send message when server starts and stops

I have a simply camel MINA server using the JAVA DSL, and I am running like the example documented here:
Running Camel standalone and have it keep running in JAVA
MINA 2 Component
Currently this server receives reports from a queue, updates them, and then sends them away to the next server. A very simple code:
public class MyApp_B {
private Main main;
public static void main(String... args) throws Exception {
MyApp_B loadbalancer = new MyApp_B();
loadbalancer.boot();
}
public void boot() throws Exception {
main = new Main();
main.enableHangupSupport();
main.addRouteBuilder(
new RouteBuilder(){
#Override
public void configure() throws Exception {
from("mina:tcp://localhost:9991")
.setHeader("minaServer", constant("localhost:9991"))
.beanRef("service.Reporting", "updateReport")
.to("direct:messageSender1");
from("direct:messageSender1")
.to("mina:tcp://localhost:9993")
.log("${body}");
}
}
);
System.out.println("Starting Camel MyApp_B. Use ctrl + c to terminate the JVM.\n");
main.run();
}
}
Now, I would like to know if it is possible to do two things:
Make this server send a message to a master server when it starts running. This is an "Hello" message with this server's information basically.
Tell the master server to forget him when I shut it down pressing CTRL+C or doing something else.
I have also read this:
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/support/ServiceSupport.html#doStart%28%29
technically, by overriding the doStart and doStop methods I should get the intended behavior, however, those methods (specially the doStop method) don't work at all.
Is there a way to do this ? If yes how? If not, what are my options?
Thanks in advance, Pedro.
The code does work properly after all. The problem is my IDE, Eclipse. When using the Terminate button, Eclipse simply kills the process instead of send the CTRL+C signal to it. Furthermore it looks like Eclipse has no way of being able to send a CTRL+C signal to a process running on its console.
I have also created a discussion on Eclipse's official forums:
http://www.eclipse.org/forums/index.php/m/1176961/#msg_1176961
And may it some day help some one in a situation similar to mine.

Design(Classes, methods, interfaces) of real time applications(server/client)

I´ve been looking for a good book or article about this topic but didnt find much. I didnt find a good example - piece of code - for a specific scenario. Like clients/server conversation.
In my application´s protocol they have to send/recieve messages. Like:
Server want to send a file to a client
Client can accpet or no,
if he accepts, server will send bytes over the same connection/socket.
The rest of my application all uses blocking methods, server has a method
Heres what I did:
Server method:
public synchronized void sendFile(File file)
{
//send messsage asking if I can send a file
//block on read, waiting for client responde
//if client answers yes, start sending the bytes
//else return
}
Client methods:
public void reciveCommand()
{
//read/listen for a command from socket
//if is a send file command handleSendFileCommand();
//after the return of handleSendFileCommand() listen for another command
}
public void handleSendFileCommand()
{
//get the file server want to send
//check if it already has the file
//if it already has, then send a command to the socket saying it already has and return
//else send a command saying server can send the file
//create a FileInputStream, recive bytes and then return method
}
I am 100% sure this is wrong because, there is no way server and clients would talk bidirecional, I mean, when server wants to send a command to a server, they have to follow an order of commands until that conversation is finished, only then, they can send/recive another sequence of commands. Thats why I made all methods that send requests synchronized
It didnt took me a lot of time to realize I need to study about design patterns for that kind of application...
I read about Chain of Responsibility design pattern but I dont get it how can I use it or another good design pattern in that situation.
I hope someone can help me with some code example-like.
Thanks in advance
synchronized keyword in Java means something completely different - it marks a method or a code block as a critical section that only single thread can execute at a time. You don't need it here.
Then, a TCP connection is bi-directional on the byte-stream level. The synchronization between the server and a client is driven by the messages exchanged. Think of a client (same pretty much applies to the server) as a state machine. Some types of messages are acceptable in the current state, some are not, some switch the node into different state.
Since you are looking into design patterns, the State pattern is very applicable here.

Categories