Implemented standalone server, fixed breaking bugs
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
package io.anuke.mindustry;
|
||||
|
||||
import io.anuke.mindustry.core.*;
|
||||
import io.anuke.mindustry.io.BundleLoader;
|
||||
import io.anuke.mindustry.io.BlockLoader;
|
||||
import io.anuke.mindustry.io.BundleLoader;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.modules.ModuleCore;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
@@ -23,4 +24,11 @@ public class Mindustry extends ModuleCore {
|
||||
module(netClient = new NetClient());
|
||||
module(netCommon = new NetCommon());
|
||||
}
|
||||
|
||||
//hack
|
||||
@Override
|
||||
public void render() {
|
||||
super.render();
|
||||
Inputs.update();
|
||||
}
|
||||
}
|
||||
|
||||
25
core/src/io/anuke/mindustry/MindustryServer.java
Normal file
25
core/src/io/anuke/mindustry/MindustryServer.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package io.anuke.mindustry;
|
||||
|
||||
import io.anuke.mindustry.core.*;
|
||||
import io.anuke.mindustry.io.BlockLoader;
|
||||
import io.anuke.mindustry.io.BundleLoader;
|
||||
import io.anuke.ucore.modules.ModuleCore;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class MindustryServer extends ModuleCore {
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
headless = true;
|
||||
|
||||
BundleLoader.load();
|
||||
BlockLoader.load();
|
||||
|
||||
module(logic = new Logic());
|
||||
module(world = new World());
|
||||
module(netServer = new NetServer());
|
||||
module(netCommon = new NetCommon());
|
||||
module(serverControl = new ServerControl());
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,8 @@ public class Vars{
|
||||
//whether to hide ui, only on debug
|
||||
public static boolean showUI = true;
|
||||
|
||||
public static boolean headless = false;
|
||||
|
||||
public static float controllerMin = 0.25f;
|
||||
|
||||
public static float baseControllerSpeed = 11f;
|
||||
@@ -89,6 +91,7 @@ public class Vars{
|
||||
public static NetCommon netCommon;
|
||||
public static NetServer netServer;
|
||||
public static NetClient netClient;
|
||||
public static ServerControl serverControl;
|
||||
|
||||
public static Player player;
|
||||
|
||||
|
||||
@@ -137,8 +137,7 @@ public class Control extends Module{
|
||||
Events.on(PlayEvent.class, () -> {
|
||||
renderer.clearTiles();
|
||||
|
||||
player.x = world.getCore().worldx();
|
||||
player.y = world.getCore().worldy() - tilesize*2;
|
||||
player.set(world.getSpawnX(), world.getSpawnY());
|
||||
|
||||
Core.camera.position.set(player.x, player.y, 0);
|
||||
|
||||
@@ -263,7 +262,6 @@ public class Control extends Module{
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
Inputs.update();
|
||||
|
||||
if(Gdx.input != proxy){
|
||||
Gdx.input = proxy;
|
||||
@@ -352,5 +350,6 @@ public class Control extends Module{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ public class NetClient extends Module {
|
||||
public void update(){
|
||||
if(!Net.client()) return;
|
||||
|
||||
if(!state.is(State.menu) && Net.active()){
|
||||
if(!state.is(State.menu)){
|
||||
if(gotData) sync();
|
||||
}else if(!connecting){
|
||||
Net.disconnect();
|
||||
|
||||
@@ -22,29 +22,29 @@ public class NetCommon extends Module {
|
||||
|
||||
public NetCommon(){
|
||||
|
||||
Net.handleServer(ShootPacket.class, (id, packet) -> {
|
||||
Net.handle(ShootPacket.class, (packet) -> {
|
||||
Player player = playerGroup.getByID(packet.playerid);
|
||||
|
||||
Weapon weapon = (Weapon) Upgrade.getByID(packet.weaponid);
|
||||
weapon.shoot(player, packet.x, packet.y, packet.rotation);
|
||||
});
|
||||
|
||||
Net.handleServer(PlacePacket.class, (id, packet) -> {
|
||||
Net.handle(PlacePacket.class, (packet) -> {
|
||||
control.input().placeBlockInternal(packet.x, packet.y, Block.getByID(packet.block), packet.rotation, true, false);
|
||||
|
||||
Recipe recipe = Recipes.getByResult(Block.getByID(packet.block));
|
||||
if (recipe != null) state.inventory.removeItems(recipe.requirements);
|
||||
});
|
||||
|
||||
Net.handleServer(BreakPacket.class, (id, packet) -> {
|
||||
Net.handle(BreakPacket.class, (packet) -> {
|
||||
control.input().breakBlockInternal(packet.x, packet.y, false);
|
||||
});
|
||||
|
||||
Net.handleServer(ChatPacket.class, (id, packet) -> {
|
||||
Net.handle(ChatPacket.class, (packet) -> {
|
||||
ui.chatfrag.addMessage(packet.text, colorizeName(packet.id, packet.name));
|
||||
});
|
||||
|
||||
Net.handleServer(WeaponSwitchPacket.class, (id, packet) -> {
|
||||
Net.handle(WeaponSwitchPacket.class, (packet) -> {
|
||||
Player player = playerGroup.getByID(packet.playerid);
|
||||
|
||||
if (player == null) return;
|
||||
@@ -53,17 +53,17 @@ public class NetCommon extends Module {
|
||||
player.weaponRight = (Weapon) Upgrade.getByID(packet.right);
|
||||
});
|
||||
|
||||
Net.handleServer(BlockTapPacket.class, (id, packet) -> {
|
||||
Net.handle(BlockTapPacket.class, (packet) -> {
|
||||
Tile tile = world.tile(packet.position);
|
||||
tile.block().tapped(tile);
|
||||
});
|
||||
|
||||
Net.handleServer(BlockConfigPacket.class, (id, packet) -> {
|
||||
Net.handle(BlockConfigPacket.class, (packet) -> {
|
||||
Tile tile = world.tile(packet.position);
|
||||
if (tile != null) tile.block().configure(tile, packet.data);
|
||||
});
|
||||
|
||||
Net.handleServer(PlayerDeathPacket.class, (id, packet) -> {
|
||||
Net.handle(PlayerDeathPacket.class, (packet) -> {
|
||||
Player player = playerGroup.getByID(packet.id);
|
||||
if(player == null) return;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class NetCommon extends Module {
|
||||
packet.name = null;
|
||||
packet.text = message;
|
||||
Net.send(packet, SendMode.tcp);
|
||||
ui.chatfrag.addMessage(message, null);
|
||||
if(!headless) ui.chatfrag.addMessage(message, null);
|
||||
}
|
||||
|
||||
public String colorizeName(int id, String name){
|
||||
|
||||
@@ -208,7 +208,7 @@ public class NetServer extends Module{
|
||||
}
|
||||
|
||||
public void update(){
|
||||
if(!closing && Net.active() && state.is(State.menu)){
|
||||
if(!closing && Net.server() && state.is(State.menu)){
|
||||
closing = true;
|
||||
weapons.clear();
|
||||
ui.loadfrag.show("$text.server.closing");
|
||||
|
||||
138
core/src/io/anuke/mindustry/core/ServerControl.java
Normal file
138
core/src/io/anuke/mindustry/core/ServerControl.java
Normal file
@@ -0,0 +1,138 @@
|
||||
package io.anuke.mindustry.core;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.Packets.ChatPacket;
|
||||
import io.anuke.mindustry.world.Map;
|
||||
import io.anuke.ucore.UCore;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Sounds;
|
||||
import io.anuke.ucore.modules.Module;
|
||||
import io.anuke.ucore.util.ColorCodes;
|
||||
import io.anuke.ucore.util.CommandHandler;
|
||||
import io.anuke.ucore.util.CommandHandler.Command;
|
||||
import io.anuke.ucore.util.CommandHandler.Response;
|
||||
import io.anuke.ucore.util.CommandHandler.ResponseType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
import static io.anuke.ucore.util.ColorCodes.*;
|
||||
|
||||
public class ServerControl extends Module {
|
||||
private final CommandHandler handler = new CommandHandler("");
|
||||
|
||||
public ServerControl(){
|
||||
Effects.setScreenShakeProvider((a, b) -> {});
|
||||
Effects.setEffectProvider((a, b, c, d, e) -> {});
|
||||
Sounds.setHeadless(true);
|
||||
|
||||
//override default handling
|
||||
Net.handle(ChatPacket.class, (packet) -> {
|
||||
info("&y" + (packet.name == null ? "" : packet.name) + ": &lb{0}", packet.text);
|
||||
});
|
||||
|
||||
registerCommands();
|
||||
Thread thread = new Thread(this::readCommands, "Server Controls");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
|
||||
info("&lcServer loaded. Type &ly'help'&lc for help.");
|
||||
}
|
||||
|
||||
private void registerCommands(){
|
||||
handler.register("help", "", "Displays this command list.", arg -> {
|
||||
info("Commands:");
|
||||
for(Command command : handler.getCommandList()){
|
||||
print(" &y" + command.text + (command.params.isEmpty() ? "" : " ") + command.params + " - &lm" + command.description);
|
||||
}
|
||||
});
|
||||
|
||||
handler.register("exit", "", "Exit the server application.", arg -> {
|
||||
info("Shutting down server.");
|
||||
Net.dispose();
|
||||
Gdx.app.exit();
|
||||
});
|
||||
|
||||
handler.register("stop", "", "Stop hosting the server.", arg -> {
|
||||
Net.closeServer();
|
||||
state.set(State.menu);
|
||||
});
|
||||
|
||||
handler.register("host", "<mapname>", "Open the server with a specific map.", arg -> {
|
||||
if(state.is(State.playing)){
|
||||
err("Already hosting. Type 'stop' to stop hosting first.");
|
||||
}
|
||||
|
||||
String search = arg[0];
|
||||
Map result = null;
|
||||
for(Map map : world.maps().list()){
|
||||
if(map.name.equalsIgnoreCase(search))
|
||||
result = map;
|
||||
}
|
||||
|
||||
if(result == null){
|
||||
err("No map with name &y'{0}'&lg found.", search);
|
||||
return;
|
||||
}
|
||||
|
||||
info("Loading map...");
|
||||
logic.reset();
|
||||
world.loadMap(result);
|
||||
state.set(State.playing);
|
||||
info("Map loaded.");
|
||||
|
||||
try {
|
||||
Net.host(port);
|
||||
info("Server opened.");
|
||||
}catch (IOException e){
|
||||
UCore.error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void readCommands(){
|
||||
Scanner scan = new Scanner(System.in);
|
||||
System.out.print(LIGHT_BLUE + "> " + RESET);
|
||||
while(true){
|
||||
String line = scan.nextLine();
|
||||
|
||||
Gdx.app.postRunnable(() -> {
|
||||
Response response = handler.handleMessage(line);
|
||||
|
||||
if (response.type == ResponseType.unknownCommand) {
|
||||
err("Invalid command. Type 'help' for help.");
|
||||
} else if (response.type == ResponseType.invalidArguments) {
|
||||
err("Invalid command arguments. Usage: " + response.command.text + " " + response.command.params);
|
||||
}
|
||||
|
||||
System.out.print(LIGHT_BLUE + "> " + RESET);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void print(String text, Object... args){
|
||||
System.out.println(format(text, args) + RESET);
|
||||
}
|
||||
|
||||
private void info(String text, Object... args){
|
||||
print(LIGHT_GREEN + BOLD + format(text, args));
|
||||
}
|
||||
|
||||
private void err(String text, Object... args){
|
||||
print(LIGHT_RED + BOLD + format(text, args));
|
||||
}
|
||||
|
||||
private String format(String text, Object... args){
|
||||
for(int i = 0; i < args.length; i ++){
|
||||
text = text.replace("{" + i + "}", args[i].toString());
|
||||
}
|
||||
|
||||
for(String color : ColorCodes.getColorCodes()){
|
||||
text = text.replace("&" + color, ColorCodes.getColorText(color));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class World extends Module{
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(!(Net.client()))
|
||||
if(!Net.client())
|
||||
pathfind.update();
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class World extends Module{
|
||||
}
|
||||
|
||||
public float getSpawnY(){
|
||||
return core.worldy() - tilesize/2;
|
||||
return core.worldy() - tilesize*2;
|
||||
}
|
||||
|
||||
public boolean solid(int x, int y){
|
||||
|
||||
@@ -147,7 +147,7 @@ public class Maps implements Disposable{
|
||||
if(arr != null){ //can be an empty map file
|
||||
for(Map map : arr){
|
||||
map.pixmap = new Pixmap(file.sibling(map.name + ".png"));
|
||||
map.texture = new Texture(map.pixmap);
|
||||
if(!headless) map.texture = new Texture(map.pixmap);
|
||||
maps.put(map.id, map);
|
||||
mapNames.put(map.name, map);
|
||||
lastID = Math.max(lastID, map.id);
|
||||
@@ -164,7 +164,7 @@ public class Maps implements Disposable{
|
||||
@Override
|
||||
public void dispose(){
|
||||
for(Map map : maps.values()){
|
||||
map.texture.dispose();
|
||||
if(map.texture != null) map.texture.dispose();
|
||||
map.pixmap.dispose();
|
||||
}
|
||||
maps.clear();
|
||||
|
||||
@@ -15,6 +15,9 @@ import io.anuke.ucore.function.Consumer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static io.anuke.mindustry.Vars.headless;
|
||||
import static io.anuke.mindustry.Vars.ui;
|
||||
|
||||
public class Net{
|
||||
public static final int version = 13;
|
||||
|
||||
@@ -29,6 +32,15 @@ public class Net{
|
||||
|
||||
private static IntMap<StreamBuilder> streams = new IntMap<>();
|
||||
|
||||
/**Display a network error.*/
|
||||
public static void showError(String text){
|
||||
if(!headless){
|
||||
ui.showError(text);
|
||||
}else{
|
||||
UCore.log(text);
|
||||
}
|
||||
}
|
||||
|
||||
/**Sets the client loaded status, or whether it will recieve normal packets from the server.*/
|
||||
public static void setClientLoaded(boolean loaded){
|
||||
clientLoaded = loaded;
|
||||
|
||||
@@ -266,7 +266,7 @@ public class NetworkIO {
|
||||
world.loadMap(world.maps().getMap(mapid), seed);
|
||||
renderer.clearTiles();
|
||||
|
||||
player.set(world.getCore().worldx(), world.getCore().worldy());
|
||||
player.set(world.getSpawnX(), world.getSpawnY());
|
||||
|
||||
for(int x = 0; x < world.width(); x ++){
|
||||
for(int y = 0; y < world.height(); y ++){
|
||||
|
||||
Reference in New Issue
Block a user