diff --git a/src/main/java/arcanitor/civilengineering/CivilEngineering.java b/src/main/java/arcanitor/civilengineering/CivilEngineering.java index e62cd74..e6300a7 100644 --- a/src/main/java/arcanitor/civilengineering/CivilEngineering.java +++ b/src/main/java/arcanitor/civilengineering/CivilEngineering.java @@ -1,9 +1,8 @@ package arcanitor.civilengineering; -import arcanitor.civilengineering.bridge.OutgoingMessageHandler; import arcanitor.civilengineering.eventhandlers.FMLEventHandler; -import arcanitor.civilengineering.bridge.IncomingMessageHandler; -import arcanitor.civilengineering.server.ServerChatWriter; +import arcanitor.civilengineering.bridge.MessageHandler; +import arcanitor.civilengineering.bridge.ServerChatHelper; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.*; @@ -26,8 +25,8 @@ public class CivilEngineering { public static CivilEngineering instance; public static Logger logger; - public static Thread incomingMessageThread = new Thread(new IncomingMessageHandler()); - public static Thread outgoingMessageThread = new Thread(new OutgoingMessageHandler()); + public static Thread incomingMessageThread = new Thread(new MessageHandler()); + //public static Thread outgoingMessageThread = new Thread(new OutgoingMessageHandler()); @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) { @@ -44,7 +43,7 @@ public class CivilEngineering { @Mod.EventHandler public void postInit(FMLPostInitializationEvent event) { FMLEventHandler.postInit(event); - MinecraftForge.EVENT_BUS.register(ServerChatWriter.class); + MinecraftForge.EVENT_BUS.register(ServerChatHelper.class); } @Mod.EventHandler diff --git a/src/main/java/arcanitor/civilengineering/bridge/IncomingMessageHandler.java b/src/main/java/arcanitor/civilengineering/bridge/IncomingMessageHandler.java deleted file mode 100644 index 0d1f7b2..0000000 --- a/src/main/java/arcanitor/civilengineering/bridge/IncomingMessageHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -package arcanitor.civilengineering.bridge; - -import arcanitor.civilengineering.CivilEngineering; -import arcanitor.civilengineering.Config; -import arcanitor.civilengineering.server.ServerChatWriter; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; - -public class IncomingMessageHandler implements Runnable { - private HttpURLConnection connection = null; - - public void run() { - CivilEngineering.logger.info("Receiving Network Thread starting."); - try { - connect(Config.connectURL,Config.authToken); - BufferedReader input = - new BufferedReader(new InputStreamReader(connection.getInputStream())); - String line; - while ((line = input.readLine( )) != null) { - if(CivilEngineering.incomingMessageThread.isInterrupted()) throw new InterruptedException(); - - CivilEngineering.logger.debug(line); - ServerChatWriter.messages.add(ApiMessage.decode(line)); - } - - } catch (Exception e) { - - if (e instanceof InterruptedException) { - connection.disconnect(); //close the connection - CivilEngineering.logger.info("Receiving connection closed."); - } else if (e instanceof IOException) { - CivilEngineering.outgoingMessageThread.interrupt(); - CivilEngineering.logger.error("Error connecting to bridge server!"); - CivilEngineering.logger.error(e.getMessage()); - } - } - - } - - private void connect(String serverURL, String token) throws IOException { - URL url = new URL(serverURL+"/api/stream"); //parse the server URL - URLConnection urlConnection = url.openConnection(); - - //set connection properties - connection = (HttpURLConnection)urlConnection; - connection.setAllowUserInteraction(false); - connection.setInstanceFollowRedirects(true); - - if (token != null) { - connection.setRequestProperty ("Authorization", "Bearer " + token); - } - } -} diff --git a/src/main/java/arcanitor/civilengineering/bridge/MessageHandler.java b/src/main/java/arcanitor/civilengineering/bridge/MessageHandler.java new file mode 100644 index 0000000..4f5b9f8 --- /dev/null +++ b/src/main/java/arcanitor/civilengineering/bridge/MessageHandler.java @@ -0,0 +1,106 @@ +package arcanitor.civilengineering.bridge; + +import arcanitor.civilengineering.CivilEngineering; +import arcanitor.civilengineering.Config; +import com.google.gson.Gson; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static java.lang.Thread.sleep; + +public class MessageHandler implements Runnable { + + public static ConcurrentLinkedQueue xmitQueue = new ConcurrentLinkedQueue<>(); + public static ConcurrentLinkedQueue rcvQueue = new ConcurrentLinkedQueue<>(); + + public void run() { + CivilEngineering.logger.info("Connecting to bridge server @ "+Config.connectURL); + try { + while(true) { + transmitFromQueue(); + receiveToQueue(); + sleep(50); + } + } catch (Exception e) { + + if (e instanceof InterruptedException) { + CivilEngineering.logger.info("Connection closed."); + } else if (e instanceof IOException) { + CivilEngineering.logger.error("Error connecting to bridge server!"); + CivilEngineering.logger.error(e.getMessage()); + } + } + + } + + private void transmitFromQueue() throws IOException { + ApiMessage nextMessage = xmitQueue.poll(); + while(nextMessage != null) { + //open a connection + URL url = new URL(Config.connectURL + "/api/message"); + URLConnection urlConnection = url.openConnection(); + HttpURLConnection connection = (HttpURLConnection)urlConnection; + + //configure the connection + connection.setAllowUserInteraction(false); + connection.setInstanceFollowRedirects(true); + connection.setRequestProperty("Content-Type","application/json"); + connection.setRequestMethod("POST"); + if (Config.authToken != null) { + connection.setRequestProperty ("Authorization", "Bearer " + Config.authToken); + } + + //encode the ApiMessage for sending + String json = nextMessage.encode(); + + //send the message + connection.setDoOutput(true); + DataOutputStream post = new DataOutputStream(connection.getOutputStream()); + post.writeBytes(json); + post.flush(); + post.close(); + + if (connection.getResponseCode()!=200) { + CivilEngineering.logger.error("Server returned "+connection.getResponseCode()); + break; + } + } + + } + private void receiveToQueue() throws IOException { + ApiMessage[] messages; + + //open a connection + URL url = new URL(Config.connectURL + "/api/messages"); + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + + //configure the connection + con.setAllowUserInteraction(false); + con.setInstanceFollowRedirects(true); + if (Config.authToken != null) { + con.setRequestProperty ("Authorization", "Bearer " + Config.authToken); + } + + //read the messages + BufferedReader input = new BufferedReader(new InputStreamReader(con.getInputStream())); + StringBuilder data = new StringBuilder(); + String line; + while((line = input.readLine( )) != null) { + data.append(line); + } + + //decode the messages + Gson gson = new Gson(); + messages = gson.fromJson(data.toString(),ApiMessage[].class); + + //enqueue the messages + if(messages.length>0) for (ApiMessage msg : messages) rcvQueue.add(msg); + } +} diff --git a/src/main/java/arcanitor/civilengineering/bridge/OutgoingMessageHandler.java b/src/main/java/arcanitor/civilengineering/bridge/OutgoingMessageHandler.java index a770d37..daf6294 100644 --- a/src/main/java/arcanitor/civilengineering/bridge/OutgoingMessageHandler.java +++ b/src/main/java/arcanitor/civilengineering/bridge/OutgoingMessageHandler.java @@ -67,10 +67,6 @@ public class OutgoingMessageHandler implements Runnable { post.flush(); post.close(); - int response = connection.getResponseCode(); - - connection.disconnect(); - - return response; + return connection.getResponseCode(); } } diff --git a/src/main/java/arcanitor/civilengineering/server/ServerChatWriter.java b/src/main/java/arcanitor/civilengineering/bridge/ServerChatHelper.java similarity index 75% rename from src/main/java/arcanitor/civilengineering/server/ServerChatWriter.java rename to src/main/java/arcanitor/civilengineering/bridge/ServerChatHelper.java index 372ddc2..30166c1 100644 --- a/src/main/java/arcanitor/civilengineering/server/ServerChatWriter.java +++ b/src/main/java/arcanitor/civilengineering/bridge/ServerChatHelper.java @@ -1,20 +1,18 @@ -package arcanitor.civilengineering.server; +package arcanitor.civilengineering.bridge; -import arcanitor.civilengineering.CivilEngineering; import arcanitor.civilengineering.bridge.ApiMessage; +import arcanitor.civilengineering.bridge.MessageHandler; import net.minecraft.util.text.TextComponentString; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; -import java.util.concurrent.ConcurrentLinkedQueue; - -public class ServerChatWriter { - public static ConcurrentLinkedQueue messages = new ConcurrentLinkedQueue(); +public class ServerChatHelper { + //public static ConcurrentLinkedQueue messages = new ConcurrentLinkedQueue(); @SubscribeEvent public static void onServerUpdate(TickEvent.ServerTickEvent event) { - ApiMessage nextMessage = messages.poll(); + ApiMessage nextMessage = MessageHandler.rcvQueue.poll(); if (nextMessage != null) { String user = nextMessage.getUsername(); diff --git a/src/main/java/arcanitor/civilengineering/command/BridgeCommand.java b/src/main/java/arcanitor/civilengineering/command/BridgeCommand.java index 5b5448b..0f2365b 100644 --- a/src/main/java/arcanitor/civilengineering/command/BridgeCommand.java +++ b/src/main/java/arcanitor/civilengineering/command/BridgeCommand.java @@ -1,11 +1,10 @@ package arcanitor.civilengineering.command; import arcanitor.civilengineering.CivilEngineering; +import arcanitor.civilengineering.bridge.MessageHandler; import com.google.common.collect.Lists; import net.minecraft.command.CommandBase; -import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.command.WrongUsageException; import net.minecraft.server.MinecraftServer; import javax.annotation.Nonnull; @@ -44,15 +43,11 @@ public class BridgeCommand extends CommandBase { String cmd = args[0]; if (cmd.toLowerCase().equals("connect")) { if(!CivilEngineering.incomingMessageThread.isAlive()) { + CivilEngineering.incomingMessageThread = new Thread(new MessageHandler()); CivilEngineering.incomingMessageThread.start(); } - if(!CivilEngineering.outgoingMessageThread.isAlive()){ - CivilEngineering.outgoingMessageThread.start(); - } - } else if (cmd.toLowerCase().equals("disconnect")) { CivilEngineering.incomingMessageThread.interrupt(); - CivilEngineering.outgoingMessageThread.interrupt(); } } diff --git a/src/main/java/arcanitor/civilengineering/eventhandlers/ChatMessageHandler.java b/src/main/java/arcanitor/civilengineering/eventhandlers/ChatMessageHandler.java index 35055fd..bb07e20 100644 --- a/src/main/java/arcanitor/civilengineering/eventhandlers/ChatMessageHandler.java +++ b/src/main/java/arcanitor/civilengineering/eventhandlers/ChatMessageHandler.java @@ -1,8 +1,7 @@ package arcanitor.civilengineering.eventhandlers; -import arcanitor.civilengineering.CivilEngineering; import arcanitor.civilengineering.bridge.ApiMessage; -import arcanitor.civilengineering.bridge.OutgoingMessageHandler; +import arcanitor.civilengineering.bridge.MessageHandler; import net.minecraftforge.event.ServerChatEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -13,6 +12,6 @@ public class ChatMessageHandler { public static void handleServerChatEvent (ServerChatEvent event) { String message = event.getMessage().trim(); if (!message.isEmpty()) - OutgoingMessageHandler.queue.add(new ApiMessage(event.getUsername(),message)); + MessageHandler.xmitQueue.add(new ApiMessage(event.getUsername(),message)); } } diff --git a/src/main/java/arcanitor/civilengineering/eventhandlers/DeathEventHandler.java b/src/main/java/arcanitor/civilengineering/eventhandlers/DeathEventHandler.java index fdf65b6..8dad89f 100644 --- a/src/main/java/arcanitor/civilengineering/eventhandlers/DeathEventHandler.java +++ b/src/main/java/arcanitor/civilengineering/eventhandlers/DeathEventHandler.java @@ -1,9 +1,8 @@ package arcanitor.civilengineering.eventhandlers; -import arcanitor.civilengineering.CivilEngineering; import arcanitor.civilengineering.Config; import arcanitor.civilengineering.bridge.ApiMessage; -import arcanitor.civilengineering.bridge.OutgoingMessageHandler; +import arcanitor.civilengineering.bridge.MessageHandler; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.event.entity.living.LivingDeathEvent; @@ -18,7 +17,7 @@ public class DeathEventHandler { EntityLivingBase entity = event.getEntityLiving(); if (entity instanceof EntityPlayer) { String message = entity.getCombatTracker().getDeathMessage().getUnformattedText(); - OutgoingMessageHandler.queue.add(new ApiMessage("Server",message)); + MessageHandler.xmitQueue.add(new ApiMessage("Server",message)); } } } diff --git a/src/main/java/arcanitor/civilengineering/eventhandlers/FMLEventHandler.java b/src/main/java/arcanitor/civilengineering/eventhandlers/FMLEventHandler.java index b08ac6b..57ccbfe 100644 --- a/src/main/java/arcanitor/civilengineering/eventhandlers/FMLEventHandler.java +++ b/src/main/java/arcanitor/civilengineering/eventhandlers/FMLEventHandler.java @@ -21,18 +21,19 @@ public class FMLEventHandler { config = new Configuration(new File(directory.getPath(), "CivilEngineering.cfg")); Config.readConfig(); } + public static void postInit(FMLPostInitializationEvent event) { if (config.hasChanged()) { config.save(); } } + public static void serverStarting(FMLServerStartingEvent event) { event.registerServerCommand(new BridgeCommand()); CivilEngineering.incomingMessageThread.start(); - CivilEngineering.outgoingMessageThread.start(); } + public static void serverStopping(FMLServerStoppingEvent event) { CivilEngineering.incomingMessageThread.interrupt(); - CivilEngineering.outgoingMessageThread.interrupt(); } } diff --git a/src/main/java/arcanitor/civilengineering/eventhandlers/UserActionHandler.java b/src/main/java/arcanitor/civilengineering/eventhandlers/UserActionHandler.java index 11114fb..66806fd 100644 --- a/src/main/java/arcanitor/civilengineering/eventhandlers/UserActionHandler.java +++ b/src/main/java/arcanitor/civilengineering/eventhandlers/UserActionHandler.java @@ -1,11 +1,9 @@ package arcanitor.civilengineering.eventhandlers; -import arcanitor.civilengineering.CivilEngineering; import arcanitor.civilengineering.bridge.ApiMessage; -import arcanitor.civilengineering.bridge.OutgoingMessageHandler; +import arcanitor.civilengineering.bridge.MessageHandler; import net.minecraft.command.server.CommandEmote; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.event.CommandEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -25,7 +23,7 @@ public class UserActionHandler { } message = message.trim(); - OutgoingMessageHandler.queue.add(new ApiMessage(user,message,"user_action")); + MessageHandler.xmitQueue.add(new ApiMessage(user,message,"user_action")); } } }