Jump to content

Thread/Socket Gets Killed?


gudenau

Recommended Posts

I am attempting to create a Socket in a second thread to communicate with a different application. The application will have the ships stats displayed for now, but more will come later.

My problem is that my Thread/Socket seems to die as soon as the player leaves the Main Menu, any help would be appreciated.

Server (Java):


package org.gudenau.pc.kerbal.kerbaldisplay;

import java.awt.GridLayout;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class KerbalDisplay {

private final static HashMap<Integer, Class<? extends Packet>> packetMap = new HashMap<Integer, Class<? extends Packet>>();

private JFrame frame;
private JLabel active;

private void main() throws IOException {
ServerSocket server = new ServerSocket(1001);

while(true){
Socket client = server.accept();

frame = new JFrame("Kerbal Display");
JPanel panel = new JPanel(new GridLayout(2, 0));
frame.add(panel);

panel.add(new JLabel("Vessel != null:"));
active = new JLabel("false");
panel.add(active);

frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);

InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();

byte[] buffer = null;
byte tmp = -1;
int bufferOffset = -1;
int type = -1;

int count = 0;

try {
Thread.sleep(10);
} catch (InterruptedException e1) {}

while(true){
out.write(new byte[]{0, 0});

if(in.available() > 0){
tmp = (byte) in.read();

if(buffer == null){
buffer = new byte[tmp];
}else if(type == -1){
type = tmp;
bufferOffset = 0;
}else{
buffer[bufferOffset++] = tmp;

if(bufferOffset == buffer.length){
processPacket(type, buffer);
buffer = null;
type = -1;
}
}
}else{
try {
Thread.sleep(1);
} catch (InterruptedException e) {}
}

count++;

if(count >= 1024){
count = 0;
byte[] outBuffer = new byte[]{1, 0, 0};
System.out.println(outBuffer[0]);
out.write(outBuffer);
}
}
}
}

private void processPacket(int type, byte[] buffer) {
switch(type){
case 0:
active.setText((buffer[0] == 1) + "");
}
}

public static void main(String[] args) throws IOException{
new KerbalDisplay().main();
}
}

Plugin:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using System.Net;
using System.Net.Sockets;
using System.IO;

using UnityEngine;

public class HelloKerbinModController {
public void start() {
IPAddress address = IPAddress.Loopback;
IPEndPoint ipEndPoint = new IPEndPoint(address, 1001);
socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.NoDelay = false;

socket.Connect(ipEndPoint);

byte[] tmp = null;
byte data = 0;
int rec;
int tmpOffset = 0;

while(socket.IsBound){
if(socket.Available > 0){
tmp = new byte[socket.Available];
rec = socket.Receive(tmp);

for (tmpOffset = 0; tmpOffset < rec; tmpOffset++)
{
data = tmp[tmpOffset];

handleInputByte(data);
}
}
}
}

private byte[] buffer = null;
private int bufferOffset = 0;
private int type = -1;
private Socket socket;

private void handleInputByte(byte data){
if(buffer == null){
buffer = new byte[data];
bufferOffset = 0;
}
else if (type == -1)
{
type = data;
}
else {
buffer[bufferOffset++] = data;

if(bufferOffset == buffer.Length){
processPacket();
buffer = null;
type = -1;
}
}
}

private void processPacket() {
switch(type){
case 0:
sendVesselData();
break;
}
}

private void sendVesselData()
{
Vessel ship = FlightGlobals.ActiveVessel;

byte[] data = {1, 0, (byte)(ship == null ? 1 : 0) };

socket.Send(data);
}

private void informUser(String message) {
ScreenMessages.PostScreenMessage(message, 30F, ScreenMessageStyle.UPPER_RIGHT);
MonoBehaviour.print(message);
}
}

[KSPAddon(KSPAddon.Startup.MainMenu, false)]
public class HelloKerbinModConnection : MonoBehaviour
{
public void Start()
{
HelloKerbinModController hkmc = new HelloKerbinModController();
Thread thread = new Thread(hkmc.start);
thread.Start();
}
}

Link to comment
Share on other sites

I think you are misunderstanding how the KSPAddon attribute works.

[KSPAddon(KSPAddon.Startup.MainMenu, false)]

means only run while at the main menu screen. So when you switch to the Space Center (load a save), it stops your plug in as you are no longer at the Main Menu.

I'm not sure of exactly how to go about what you need.

I'd try to find a mod that runs all the time and see how they do it, I've not tried this myself but there are several issues that you might run into from reading posts on the forum.

Notably if you set run once to true, look into using KSPAddonFixed instead to get around a bug in the KSPAddon attribute.

D.

Link to comment
Share on other sites

I think you are misunderstanding how the KSPAddon attribute works.

[KSPAddon(KSPAddon.Startup.MainMenu, false)]

means only run while at the main menu screen. So when you switch to the Space Center (load a save), it stops your plug in as you are no longer at the Main Menu.

I'm not sure of exactly how to go about what you need.

I'd try to find a mod that runs all the time and see how they do it, I've not tried this myself but there are several issues that you might run into from reading posts on the forum.

Notably if you set run once to true, look into using KSPAddonFixed instead to get around a bug in the KSPAddon attribute.

D.

The boolean is a one-shot, if true it will be run every time, not kept running.

I see no KSPAddonFixed.

Link to comment
Share on other sites

From the developer's release notes on KSPAddon:

KSPAddon & AddonLoader

AddonLoader is a simple system which allows modders to instantiate Unity MonoBehaviours without need to messily overload Part, PartModule or UnitTests. To do this you tag a component in your assembly with the KSPAddon attribute. This attribute allows you to set which scene the component is instantiated in and also if it should be repeatedly instantiated upon transition into that scene. If you want the component to not be destroyed then you should set 'once' to true and manually call DontDestroyOnLoad.

The way I read that is when a class is instantiated for a scene, if the bool is set to false, it instantiates every time you transfer to the scene.

If you do not call DontDestroyOnLoad, your class is destroyed when you leave the scene, I assume that this explains why you are seeing what you are because your class is only active while you are at the main menu.

The wildcard is the fact that you are calling a new thread. I'm not sure how that is going to affect things so you will have to experiment I guess.

KSPAddonFixed is a work around Majiir has come up with for a bug in Squads handling of add-ons that set the run once bool to true. Link here has the full details.

D.

Link to comment
Share on other sites

From the developer's release notes on KSPAddon:

The way I read that is when a class is instantiated for a scene, if the bool is set to false, it instantiates every time you transfer to the scene.

If you do not call DontDestroyOnLoad, your class is destroyed when you leave the scene, I assume that this explains why you are seeing what you are because your class is only active while you are at the main menu.

The wildcard is the fact that you are calling a new thread. I'm not sure how that is going to affect things so you will have to experiment I guess.

KSPAddonFixed is a work around Majiir has come up with for a bug in Squads handling of add-ons that set the run once bool to true. Link here has the full details.

D.

Thanks, where did you find that?

Edit:

DontDestroyOnLoad does not seem to exist... I feel like a I made a great big derp.

Link to comment
Share on other sites

My quote was from Mu's post here announcing the new features in the 0.20 release.

On the DontDestroyOnLoad I am at a loss as I've never tried to use it myself.

Everything I've done is confined to flight mode or the editor and I've been allowing KSP to destroy my classes when I leave those scenes to make sure I keep all my references straight by making sure they refresh when I come back to the scene later.

D.

Link to comment
Share on other sites

Your issue is choosing MainMenu as your startpoint - most mods for overall functionality use Instantly with once as true, or use EveryScene, and once = false, and plan for whichever they use. Bear in mind that instantly starts during the load screen (as will EveryScene, I believe)

KSPAddonFixed is no longer necessary - the bug it fixes has been... fixed.

Hope that helps :)

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

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
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  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.

×
×
  • Create New...