This commit is contained in:
Anuken
2019-08-21 20:10:54 -04:00
74 changed files with 519 additions and 625 deletions

View File

@@ -1,27 +1,30 @@
package io.anuke.mindustry.desktop;
import io.anuke.arc.backends.lwjgl3.Lwjgl3Application;
import io.anuke.arc.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import io.anuke.mindustry.Mindustry;
import io.anuke.mindustry.core.Platform;
import io.anuke.arc.Files.*;
import io.anuke.arc.backends.sdl.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.desktop.steam.*;
import io.anuke.mindustry.net.*;
public class DesktopLauncher{
public static void main(String[] arg){
try{
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
config.setTitle("Mindustry");
config.setMaximized(true);
config.setBackBufferConfig(8, 8, 8, 8, 0, 0, 0);
config.setWindowedMode(900, 600);
config.setWindowIcon("icons/icon_64.png");
Platform.instance = new DesktopPlatform(arg);
Net.setClientProvider(new ArcNetClient());
Net.setServerProvider(new ArcNetServer());
new Lwjgl3Application(new Mindustry(), config);
Net.setServerProvider(new SteamServerImpl(new ArcNetServer()));
new SdlApplication(new Mindustry(), new SdlConfig(){{
title = "Mindustry";
maximized = true;
depth = 0;
stencil = 0;
width = 900;
height = 700;
setWindowIcon(FileType.Internal, "icons/icon_64.png");
}});
}catch(Throwable e){
DesktopPlatform.handleCrash(e);
}

View File

@@ -1,26 +1,30 @@
package io.anuke.mindustry.desktop;
import club.minnced.discord.rpc.*;
import io.anuke.arc.collection.Array;
import io.anuke.arc.files.FileHandle;
import io.anuke.arc.function.Consumer;
import io.anuke.arc.function.Predicate;
import com.codedisaster.steamworks.*;
import io.anuke.arc.*;
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.*;
import io.anuke.arc.util.serialization.Base64Coder;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.core.Platform;
import io.anuke.mindustry.net.CrashSender;
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.game.EventType.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.ui.dialogs.FileChooser;
import org.lwjgl.util.tinyfd.TinyFileDialogs;
import io.anuke.mindustry.net.*;
import io.anuke.mindustry.ui.dialogs.*;
import java.net.NetworkInterface;
import java.net.*;
import java.util.*;
import static io.anuke.mindustry.Vars.*;
public class DesktopPlatform extends Platform{
static boolean useDiscord = OS.is64Bit;
static boolean useDiscord = OS.is64Bit, useSteam = true;
final static String applicationId = "610508934456934412";
String[] args;
@@ -40,19 +44,55 @@ public class DesktopPlatform extends Platform{
Log.err("Failed to initialize discord.", t);
}
}
if(useSteam){
Vars.steam = true;
try{
SteamAPI.loadLibraries();
if(!SteamAPI.init()){
Log.info("Steam client not running. Make sure Steam is running!");
}else{
//times per second
float interval = 20f;
Interval i = new Interval();
//run steam callbacks
Events.on(GameLoadEvent.class, event -> {
//update callbacks
Core.app.addListener(new ApplicationListener(){
@Override
public void update(){
if(i.get(interval)){
if(SteamAPI.isSteamRunning()){
SteamAPI.runCallbacks();
}
}
}
});
//Core.app.post(() -> new ClientSteam());
});
//steam shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(SteamAPI::shutdown));
}
}catch(Exception e){
Log.err("Failed to load Steam native libraries.");
e.printStackTrace();
}
}
}
static void handleCrash(Throwable e){
Consumer<Runnable> dialog = r -> new Thread(r).start();
Consumer<Runnable> dialog = Runnable::run;
boolean badGPU = false;
if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){
dialog.accept(() -> TinyFileDialogs.tinyfd_messageBox("oh no",
dialog.accept(() -> message(
e.getMessage().contains("Couldn't create window") ? "A graphics initialization error has occured! Try to update your graphics drivers:\n" + e.getMessage() :
"Your graphics card does not support OpenGL 2.0!\n" +
"Try to update your graphics drivers.\n\n" +
"(If that doesn't work, your computer just doesn't support Mindustry.)", "ok", "error", true));
"(If that doesn't work, your computer just doesn't support Mindustry.)"));
badGPU = true;
}
@@ -60,7 +100,7 @@ public class DesktopPlatform extends Platform{
CrashSender.send(e, file -> {
if(!fbgp){
dialog.accept(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "A crash has occured. It has been saved in:\n" + file.getAbsolutePath(), "ok", "error", true));
dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath() + "\n" + (e.getMessage() == null ? "" : "\n" + e.getMessage())));
}
});
}
@@ -118,7 +158,7 @@ public class DesktopPlatform extends Platform{
String str = new String(Base64Coder.encode(result));
if(str.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID.");
if(str.equals("AAAAAAAAAOA=") || str.equals("AAAAAAAAAAA=")) throw new RuntimeException("Bad UUID.");
return str;
}catch(Exception e){
@@ -126,10 +166,14 @@ public class DesktopPlatform extends Platform{
}
}
private static void message(String message){
SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MESSAGEBOX_ERROR, "oh no", message);
}
private boolean validAddress(byte[] bytes){
if(bytes == null) return false;
byte[] result = new byte[8];
System.arraycopy(bytes, 0, result, 0, bytes.length);
return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA=");
return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA=") && !new String(Base64Coder.encode(result)).equals("AAAAAAAAAAA=");
}
}

View File

@@ -0,0 +1,156 @@
package io.anuke.mindustry.desktop.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.*;
import io.anuke.mindustry.desktop.steam.SteamServerImpl.*;
import java.nio.*;
public class SteamClientImpl implements SteamNetworkingCallback, SteamMatchmakingCallback{
private SteamNetworking snet;
private SteamMatchmaking smat;
private ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 128);
//maps steam ID -> valid net connection
private IntMap<SteamConnection> connections = new IntMap<>();
public SteamClientImpl(){
//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 = snet.isP2PPacketAvailable(0)) != 0){
try{
buffer.position(0);
snet.readP2PPacket(from, buffer, 0);
}catch(SteamException e){
e.printStackTrace();
}
}
}){{
setDaemon(true);
}}.start();*/
}
@Override
public void onP2PSessionConnectFail(SteamID steamIDRemote, P2PSessionError sessionError){
Log.info("{0} has disconnected: {1}", steamIDRemote.getAccountID(), sessionError);
}
@Override
public void onP2PSessionRequest(SteamID steamIDRemote){
snet.acceptP2PSessionWithUser(steamIDRemote);
}
@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){
}
}

View File

@@ -0,0 +1,52 @@
package io.anuke.mindustry.desktop.steam;
import com.codedisaster.steamworks.*;
import com.codedisaster.steamworks.SteamFriends.*;
public class SteamFriendsImpl implements SteamFriendsCallback{
public final SteamFriends friends;
public SteamFriendsImpl(){
friends = new SteamFriends(this);
}
@Override
public void onSetPersonaNameResponse(boolean b, boolean b1, SteamResult steamResult){
}
@Override
public void onPersonaStateChange(SteamID steamID, PersonaChange personaChange){
}
@Override
public void onGameOverlayActivated(boolean b){
}
@Override
public void onGameLobbyJoinRequested(SteamID steamID, SteamID steamID1){
}
@Override
public void onAvatarImageLoaded(SteamID steamID, int i, int i1, int i2){
}
@Override
public void onFriendRichPresenceUpdate(SteamID steamID, int i){
}
@Override
public void onGameRichPresenceJoinRequested(SteamID steamID, String s){
}
@Override
public void onGameServerChangeRequested(String s, String s1){
}
}

View File

@@ -0,0 +1,176 @@
package io.anuke.mindustry.desktop.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.net.Net.*;
import io.anuke.mindustry.net.*;
import java.io.*;
import java.nio.*;
public class SteamServerImpl implements ServerProvider, SteamNetworkingCallback, SteamMatchmakingCallback{
private final static int maxLobbyPlayers = 32;
private final PacketSerializer serializer = new PacketSerializer();
private final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(1024 * 4);
private final SteamNetworking snet = new SteamNetworking(this);
private final SteamMatchmaking smat = new SteamMatchmaking(this);
private final SteamFriendsImpl friends = new SteamFriendsImpl();
private final ServerProvider server;
//maps steam ID -> valid net connection
private IntMap<SteamConnection> steamConnections = new IntMap<>();
private SteamID currentLobby;
public SteamServerImpl(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 close(){
server.close();
if(currentLobby != null){
//TODO kick everyone who is in this lobby?
smat.leaveLobby(currentLobby);
currentLobby = null;
for(SteamConnection con : steamConnections.values()){
con.close();
}
}
}
@Override
public byte[] compressSnapshot(byte[] input){
return server.compressSnapshot(input);
}
@Override
public Iterable<? extends NetConnection> 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);
}
public class SteamConnection extends NetConnection{
final SteamID sid;
public SteamConnection(SteamID sid){
super(sid.getAccountID() + "");
this.sid = sid;
}
@Override
public void send(Object object, SendMode mode){
try{
writeBuffer.limit(writeBuffer.capacity());
writeBuffer.position(0);
serializer.write(writeBuffer, object);
writeBuffer.flip();
snet.sendP2PPacket(sid, writeBuffer, mode == SendMode.tcp ? P2PSend.Reliable : P2PSend.UnreliableNoDelay, 0);
}catch(Exception e){
Log.err(e);
Log.info("Error sending packet. Disconnecting invalid client!");
close();
SteamConnection k = steamConnections.get(sid.getAccountID());
if(k != null) steamConnections.remove(sid.getAccountID());
}
}
@Override
public void close(){
snet.closeP2PSessionWithUser(sid);
}
}
}

View File

@@ -0,0 +1,84 @@
package io.anuke.mindustry.desktop.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){
}
}