From f7eea510662900ade9aeec4673993759f88c0b4c Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 19 Aug 2019 21:32:33 -0400 Subject: [PATCH] further progress --- .gitignore | 2 + core/src/io/anuke/mindustry/Vars.java | 6 + core/src/io/anuke/mindustry/core/Control.java | 50 +++--- core/src/io/anuke/mindustry/net/Net.java | 5 +- desktop-sdl/build.gradle | 12 ++ .../mindustry/desktopsdl/DesktopLauncher.java | 3 +- .../mindustry/desktopsdl/DesktopPlatform.java | 23 ++- .../desktopsdl/steam/ClientSteam.java | 125 +++++++++++++- .../desktopsdl/steam/ServerSteam.java | 160 ++++++++++++++++++ .../desktopsdl/steam/WorkshopImpl.java | 84 +++++++++ .../io/anuke/mindustry/net/ArcNetServer.java | 5 - 11 files changed, 428 insertions(+), 47 deletions(-) create mode 100644 desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ServerSteam.java create mode 100644 desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/WorkshopImpl.java diff --git a/.gitignore b/.gitignore index 79cf5235d0..4e59ef8187 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ logs/ /tools/build/ /tests/build/ /server/build/ +saves/ +steam_appid.txt /test_files/ /annotations/build/ /desktop-sdl/build/ diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index f995df588b..bb8fc511c9 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -108,6 +108,8 @@ public class Vars{ public static boolean android; /** whether the game is running on a headless server */ public static boolean headless; + /** whether steam is enabled for this game */ + public static boolean steam; /** application data directory, equivalent to {@link io.anuke.arc.Settings#getDataDirectory()} */ public static FileHandle dataDirectory; /** data subdirectory used for screenshots */ @@ -217,6 +219,10 @@ public class Vars{ Core.settings.setAppName(appName); + if(steam){ + Core.settings.setDataDirectory(Core.files.local("saves/")); + } + dataDirectory = Core.settings.getDataDirectory(); screenshotDirectory = dataDirectory.child("screenshots/"); customMapDirectory = dataDirectory.child("maps/"); diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index b0e2eed073..644e382a41 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -350,35 +350,37 @@ public class Control implements ApplicationListener{ //display UI scale changed dialog if(Core.settings.getBool("uiscalechanged", false)){ - FloatingDialog dialog = new FloatingDialog("$confirm"); + Core.app.post(() -> Core.app.post(() -> { + FloatingDialog dialog = new FloatingDialog("$confirm"); + dialog.setFillParent(true); - float[] countdown = {60 * 11}; - Runnable exit = () -> { - Core.settings.put("uiscale", 100); - Core.settings.put("uiscalechanged", false); - settings.save(); - dialog.hide(); - Core.app.exit(); - }; + float[] countdown = {60 * 11}; + Runnable exit = () -> { + Core.settings.put("uiscale", 100); + Core.settings.put("uiscalechanged", false); + settings.save(); + dialog.hide(); + Core.app.exit(); + }; - dialog.setFillParent(false); - dialog.cont.label(() -> { - if(countdown[0] <= 0){ - exit.run(); - } - return Core.bundle.format("uiscale.reset", (int)((countdown[0] -= Time.delta()) / 60f)); - }).pad(10f).expand().left(); + dialog.cont.label(() -> { + if(countdown[0] <= 0){ + exit.run(); + } + return Core.bundle.format("uiscale.reset", (int)((countdown[0] -= Time.delta()) / 60f)); + }).pad(10f).expand().center(); - dialog.buttons.defaults().size(200f, 60f); - dialog.buttons.addButton("$uiscale.cancel", exit); + dialog.buttons.defaults().size(200f, 60f); + dialog.buttons.addButton("$uiscale.cancel", exit); - dialog.buttons.addButton("$ok", () -> { - Core.settings.put("uiscalechanged", false); - settings.save(); - dialog.hide(); - }); + dialog.buttons.addButton("$ok", () -> { + Core.settings.put("uiscalechanged", false); + settings.save(); + dialog.hide(); + }); - Core.app.post(dialog::show); + dialog.show(); + })); } } diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index d0965c3cb8..da7a7601a3 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -326,7 +326,7 @@ public class Net{ public static void dispose(){ if(clientProvider != null) clientProvider.dispose(); - if(serverProvider != null) serverProvider.dispose(); + if(serverProvider != null) serverProvider.close(); clientProvider = null; serverProvider = null; server = false; @@ -399,8 +399,5 @@ public class Net{ /** Returns a connection by ID. */ NetConnection getByID(int id); - - /** Close all connections. */ - void dispose(); } } diff --git a/desktop-sdl/build.gradle b/desktop-sdl/build.gradle index 006fda77da..08cf179196 100644 --- a/desktop-sdl/build.gradle +++ b/desktop-sdl/build.gradle @@ -47,6 +47,18 @@ task dist(type: Jar, dependsOn: classes){ } } +task steamdist(dependsOn: dist){ + doLast{ + copy{ + from "build/libs/Mindustry-linux-release.jar" + into "/home/anuke/.steam/steam/steamapps/common/Mindustry" + rename { String fileName -> + fileName.replace("Mindustry-linux-release", "desktop-release") + } + } + } +} + task ikZip(type: Zip){ def filename = "$appName-${getTarget()}-${version}" diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java index f773f0e188..260cde9c7a 100644 --- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java +++ b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java @@ -3,6 +3,7 @@ import io.anuke.arc.Files.*; import io.anuke.arc.backends.sdl.*; import io.anuke.mindustry.*; import io.anuke.mindustry.core.*; +import io.anuke.mindustry.desktopsdl.steam.*; import io.anuke.mindustry.net.*; public class DesktopLauncher{ @@ -12,7 +13,7 @@ public class DesktopLauncher{ Platform.instance = new DesktopPlatform(arg); Net.setClientProvider(new ArcNetClient()); - Net.setServerProvider(new ArcNetServer()); + Net.setServerProvider(new ServerSteam(new ArcNetServer())); new SdlApplication(new Mindustry(), new SdlConfig(){{ title = "Mindustry"; diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java index a576774732..98f7a07175 100644 --- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java +++ b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java @@ -7,14 +7,15 @@ import io.anuke.arc.backends.sdl.jni.*; import io.anuke.arc.collection.*; import io.anuke.arc.files.*; import io.anuke.arc.function.*; -import io.anuke.arc.util.Timer; import io.anuke.arc.util.*; import io.anuke.arc.util.serialization.*; +import io.anuke.mindustry.*; import io.anuke.mindustry.core.GameState.*; import io.anuke.mindustry.core.*; +import io.anuke.mindustry.desktopsdl.steam.*; import io.anuke.mindustry.game.EventType.*; -import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.Net; +import io.anuke.mindustry.net.*; import io.anuke.mindustry.ui.dialogs.*; import java.net.*; @@ -46,6 +47,7 @@ public class DesktopPlatform extends Platform{ } if(useSteam){ + Vars.steam = true; try{ SteamAPI.loadLibraries(); if(!SteamAPI.init()){ @@ -53,14 +55,23 @@ public class DesktopPlatform extends Platform{ }else{ //times per second float interval = 20f; + Interval i = new Interval(); //run steam callbacks Events.on(GameLoadEvent.class, event -> { - Timer.schedule(() -> { - if(SteamAPI.isSteamRunning()){ - SteamAPI.runCallbacks(); + //update callbacks + Core.app.addListener(new ApplicationListener(){ + @Override + public void update(){ + if(i.get(interval)){ + if(SteamAPI.isSteamRunning()){ + SteamAPI.runCallbacks(); + } + } } - }, 0f, 1f / interval); + }); + + Core.app.post(() -> new ClientSteam()); }); //steam shutdown hook Runtime.getRuntime().addShutdownHook(new Thread(SteamAPI::shutdown)); diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ClientSteam.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ClientSteam.java index d31bb75748..cecb90e97c 100644 --- a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ClientSteam.java +++ b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ClientSteam.java @@ -1,6 +1,8 @@ package io.anuke.mindustry.desktopsdl.steam; import com.codedisaster.steamworks.*; +import com.codedisaster.steamworks.SteamFriends.*; +import com.codedisaster.steamworks.SteamMatchmaking.*; import com.codedisaster.steamworks.SteamNetworking.*; import io.anuke.arc.collection.*; import io.anuke.arc.util.*; @@ -9,29 +11,36 @@ import io.anuke.mindustry.net.*; import java.nio.*; -public class ClientSteam implements SteamNetworkingCallback{ - private SteamNetworking steam; +public class ClientSteam implements SteamNetworkingCallback, SteamMatchmakingCallback{ + private SteamNetworking snet; + private SteamMatchmaking smat; + private ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 128); //maps steam ID -> valid net connection private IntMap connections = new IntMap<>(); public ClientSteam(){ - steam = new SteamNetworking(this); + //snet = new SteamNetworking(this); + //smat = new SteamMatchmaking(this); + //Log.info("Calling createLobby"); + //SteamAPICall call = smat.createLobby(LobbyType.FriendsOnly, 16); + + /* new Thread(() -> { int length; SteamID from = new SteamID(); - while((length = steam.isP2PPacketAvailable(0)) != 0){ + while((length = snet.isP2PPacketAvailable(0)) != 0){ try{ buffer.position(0); - steam.readP2PPacket(from, buffer, 0); + snet.readP2PPacket(from, buffer, 0); }catch(SteamException e){ e.printStackTrace(); } } }){{ setDaemon(true); - }}.start(); + }}.start();*/ } @Override @@ -41,7 +50,7 @@ public class ClientSteam implements SteamNetworkingCallback{ @Override public void onP2PSessionRequest(SteamID steamIDRemote){ - steam.acceptP2PSessionWithUser(steamIDRemote); + snet.acceptP2PSessionWithUser(steamIDRemote); } class SteamConnection extends NetConnection{ @@ -83,4 +92,106 @@ public class ClientSteam implements SteamNetworkingCallback{ //if(connection.isConnected()) connection.close(); } } + + @Override + public void onFavoritesListChanged(int ip, int queryPort, int connPort, int appID, int flags, boolean add, int accountID){ + + } + + @Override + public void onLobbyInvite(SteamID steamIDUser, SteamID steamIDLobby, long gameID){ + + } + + @Override + public void onLobbyEnter(SteamID steamIDLobby, int chatPermissions, boolean blocked, ChatRoomEnterResponse response){ + + } + + @Override + public void onLobbyDataUpdate(SteamID steamIDLobby, SteamID steamIDMember, boolean success){ + + } + + @Override + public void onLobbyChatUpdate(SteamID steamIDLobby, SteamID steamIDUserChanged, SteamID steamIDMakingChange, ChatMemberStateChange stateChange){ + + } + + @Override + public void onLobbyChatMessage(SteamID steamIDLobby, SteamID steamIDUser, ChatEntryType entryType, int chatID){ + + } + + @Override + public void onLobbyGameCreated(SteamID steamIDLobby, SteamID steamIDGameServer, int ip, short port){ + + } + + @Override + public void onLobbyMatchList(int lobbiesMatching){ + + } + + @Override + public void onLobbyKicked(SteamID steamIDLobby, SteamID steamIDAdmin, boolean kickedDueToDisconnect){ + + } + + @Override + public void onLobbyCreated(SteamResult result, SteamID steamIDLobby){ + Log.info("Lobby create callback"); + Log.info("Lobby {1} created? {0}", result, steamIDLobby.getAccountID()); + if(result == SteamResult.OK){ + SteamFriends friends = new SteamFriends(new SteamFriendsCallback(){ + @Override + public void onSetPersonaNameResponse(boolean success, boolean localSuccess, SteamResult result){ + + } + + @Override + public void onPersonaStateChange(SteamID steamID, PersonaChange change){ + + } + + @Override + public void onGameOverlayActivated(boolean active){ + + } + + @Override + public void onGameLobbyJoinRequested(SteamID steamIDLobby, SteamID steamIDFriend){ + Log.info("Requested {0} to join lobby {1}", steamIDFriend.getAccountID(), steamIDLobby.getAccountID()); + } + + @Override + public void onAvatarImageLoaded(SteamID steamID, int image, int width, int height){ + + } + + @Override + public void onFriendRichPresenceUpdate(SteamID steamIDFriend, int appID){ + + } + + @Override + public void onGameRichPresenceJoinRequested(SteamID steamIDFriend, String connect){ + + } + + @Override + public void onGameServerChangeRequested(String server, String password){ + + } + }); + + friends.activateGameOverlay(OverlayDialog.Friends); + //friends.activateGameOverlayInviteDialog(steamIDLobby); + } + } + + @Override + public void onFavoritesListAccountsUpdated(SteamResult result){ + + } } diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ServerSteam.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ServerSteam.java new file mode 100644 index 0000000000..229735504a --- /dev/null +++ b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/ServerSteam.java @@ -0,0 +1,160 @@ +package io.anuke.mindustry.desktopsdl.steam; + +import com.codedisaster.steamworks.*; +import com.codedisaster.steamworks.SteamMatchmaking.*; +import com.codedisaster.steamworks.SteamNetworking.*; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.desktopsdl.steam.ClientSteam.*; +import io.anuke.mindustry.net.Net.*; +import io.anuke.mindustry.net.*; + +import java.io.*; +import java.nio.*; + +public class ServerSteam implements ServerProvider, SteamNetworkingCallback, SteamMatchmakingCallback{ + private final static int maxLobbyPlayers = 32; + + private final SteamNetworking snet = new SteamNetworking(this); + private final SteamMatchmaking smat = new SteamMatchmaking(this); + private final ServerProvider server; + + //buffer for steam API calls + private ByteBuffer steamBuffer = ByteBuffer.allocateDirect(1024 * 128); + //maps steam ID -> valid net connection + private IntMap steamConnections = new IntMap<>(); + + private SteamID currentLobby; + + public ServerSteam(ServerProvider server){ + this.server = server; + } + + //server overrides + + @Override + public void host(int port) throws IOException{ + server.host(port); + smat.createLobby(LobbyType.values()[Core.settings.getInt("lobbytype", 1)], maxLobbyPlayers); + } + + @Override + public void sendStream(int id, Streamable stream){ + server.sendStream(id, stream); + } + + @Override + public void send(Object object, SendMode mode){ + server.send(object, mode); + } + + @Override + public void sendTo(int id, Object object, SendMode mode){ + server.sendTo(id, object, mode); + } + + @Override + public void sendExcept(int id, Object object, SendMode mode){ + server.sendExcept(id, object, mode); + } + + @Override + public void close(){ + server.close(); + if(currentLobby != null){ + //TODO kick everyone who is in this lobby? + smat.leaveLobby(currentLobby); + currentLobby = null; + } + } + + @Override + public byte[] compressSnapshot(byte[] input){ + return server.compressSnapshot(input); + } + + @Override + public Array getConnections(){ + return server.getConnections(); + } + + @Override + public NetConnection getByID(int id){ + return server.getByID(id); + } + + //steam lobby overrides + + @Override + public void onFavoritesListChanged(int ip, int queryPort, int connPort, int appID, int flags, boolean add, int accountID){ + + } + + @Override + public void onLobbyInvite(SteamID steamIDUser, SteamID steamIDLobby, long gameID){ + + } + + @Override + public void onLobbyEnter(SteamID steamIDLobby, int chatPermissions, boolean blocked, ChatRoomEnterResponse response){ + + } + + @Override + public void onLobbyDataUpdate(SteamID steamIDLobby, SteamID steamIDMember, boolean success){ + + } + + @Override + public void onLobbyChatUpdate(SteamID steamIDLobby, SteamID steamIDUserChanged, SteamID steamIDMakingChange, ChatMemberStateChange stateChange){ + + } + + @Override + public void onLobbyChatMessage(SteamID steamIDLobby, SteamID steamIDUser, ChatEntryType entryType, int chatID){ + + } + + @Override + public void onLobbyGameCreated(SteamID steamIDLobby, SteamID steamIDGameServer, int ip, short port){ + + } + + @Override + public void onLobbyMatchList(int lobbiesMatching){ + + } + + @Override + public void onLobbyKicked(SteamID steamIDLobby, SteamID steamIDAdmin, boolean kickedDueToDisconnect){ + + } + + @Override + public void onLobbyCreated(SteamResult result, SteamID steamIDLobby){ + Log.info("Lobby create callback"); + Log.info("Lobby {1} created? {0}", result, steamIDLobby.getAccountID()); + if(result == SteamResult.OK){ + currentLobby = steamIDLobby; + } + } + + @Override + public void onFavoritesListAccountsUpdated(SteamResult result){ + + } + + //steam p2p network overrides + + @Override + public void onP2PSessionConnectFail(SteamID steamIDRemote, P2PSessionError sessionError){ + + } + + @Override + public void onP2PSessionRequest(SteamID steamIDRemote){ + //accept users on request + snet.acceptP2PSessionWithUser(steamIDRemote); + } +} diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/WorkshopImpl.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/WorkshopImpl.java new file mode 100644 index 0000000000..a4e59a9b54 --- /dev/null +++ b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/steam/WorkshopImpl.java @@ -0,0 +1,84 @@ +package io.anuke.mindustry.desktopsdl.steam; + +import com.codedisaster.steamworks.*; +import com.codedisaster.steamworks.SteamRemoteStorage.*; +import io.anuke.mindustry.maps.*; + +public class WorkshopImpl implements SteamUGCCallback{ + private SteamUGC ugc = new SteamUGC(this); + + public void publishMap(Map map){ + ugc.createItem(1127400, WorkshopFileType.GameManagedItem); + } + + @Override + public void onUGCQueryCompleted(SteamUGCQuery query, int numResultsReturned, int totalMatchingResults, boolean isCachedData, SteamResult result){ + //ugc.submitItemUpdate() + + } + + @Override + public void onSubscribeItem(SteamPublishedFileID publishedFileID, SteamResult result){ + + } + + @Override + public void onUnsubscribeItem(SteamPublishedFileID publishedFileID, SteamResult result){ + + } + + @Override + public void onRequestUGCDetails(SteamUGCDetails details, SteamResult result){ + + } + + @Override + public void onCreateItem(SteamPublishedFileID publishedFileID, boolean needsToAcceptWLA, SteamResult result){ + //TODO + } + + @Override + public void onSubmitItemUpdate(SteamPublishedFileID publishedFileID, boolean needsToAcceptWLA, SteamResult result){ + + } + + @Override + public void onDownloadItemResult(int appID, SteamPublishedFileID publishedFileID, SteamResult result){ + + } + + @Override + public void onUserFavoriteItemsListChanged(SteamPublishedFileID publishedFileID, boolean wasAddRequest, SteamResult result){ + + } + + @Override + public void onSetUserItemVote(SteamPublishedFileID publishedFileID, boolean voteUp, SteamResult result){ + + } + + @Override + public void onGetUserItemVote(SteamPublishedFileID publishedFileID, boolean votedUp, boolean votedDown, boolean voteSkipped, SteamResult result){ + + } + + @Override + public void onStartPlaytimeTracking(SteamResult result){ + + } + + @Override + public void onStopPlaytimeTracking(SteamResult result){ + + } + + @Override + public void onStopPlaytimeTrackingForAllItems(SteamResult result){ + + } + + @Override + public void onDeleteItem(SteamPublishedFileID publishedFileID, SteamResult result){ + + } +} diff --git a/net/src/io/anuke/mindustry/net/ArcNetServer.java b/net/src/io/anuke/mindustry/net/ArcNetServer.java index de3ce52203..260796d189 100644 --- a/net/src/io/anuke/mindustry/net/ArcNetServer.java +++ b/net/src/io/anuke/mindustry/net/ArcNetServer.java @@ -220,11 +220,6 @@ public class ArcNetServer implements ServerProvider{ } } - @Override - public void dispose(){ - close(); - } - private void handleException(Throwable e){ Time.run(0f, () -> { throw new RuntimeException(e);