package ethanjones.cubes.core.platform; import ethanjones.cubes.core.localization.Localization; import ethanjones.cubes.core.logging.Log; import ethanjones.cubes.core.settings.Keybinds; import ethanjones.cubes.core.system.Branding; import ethanjones.cubes.core.system.CubesException; import ethanjones.cubes.core.system.Debug; import ethanjones.cubes.graphics.Graphics; import ethanjones.cubes.graphics.Screenshot; import ethanjones.cubes.graphics.menu.Menu; import ethanjones.cubes.graphics.menu.MenuManager; import ethanjones.cubes.graphics.menus.ClientErrorMenu.UnresponsiveIntegratedServerMenu; import ethanjones.cubes.graphics.menus.MainMenu; import ethanjones.cubes.graphics.menus.SingleplayerLoadingMenu; import ethanjones.cubes.graphics.menus.SplashMenu; import ethanjones.cubes.input.InputChain; import ethanjones.cubes.side.client.CubesClient; import ethanjones.cubes.side.common.Cubes; import ethanjones.cubes.side.common.Side; import ethanjones.cubes.side.server.CubesServer; import ethanjones.cubes.side.server.integrated.IntegratedServer; import ethanjones.cubes.world.client.ClientSaveManager; import ethanjones.cubes.world.client.WorldClient; import ethanjones.cubes.world.save.Gamemode; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import java.util.concurrent.atomic.AtomicBoolean; public class ClientAdapter implements AdapterInterface { private Menu menu; private IntegratedServer cubesServer; private CubesClient cubesClient; private CubesCmdLineOptions.ClientCmdLineOptions options; private Thread thread; private AtomicBoolean shownSplash = new AtomicBoolean(false); private AtomicBoolean setupCubes = new AtomicBoolean(false); private AtomicBoolean setupClient = new AtomicBoolean(false); private AtomicBoolean setupMenu = new AtomicBoolean(false); public ClientAdapter() { Adapter.setInterface(this); } @Override public void create() { try { Gdx.graphics.setTitle(Branding.DEBUG); thread = Thread.currentThread(); thread.setName(getSide().name()); options = new CubesCmdLineOptions.ClientCmdLineOptions(); options.parse(); Cubes.preInit(this); } catch (StopLoopException e) { Log.debug(e); } catch (Exception e) { Debug.crash(e); } } @Override public void setClient(CubesClient cubesClient) throws UnsupportedOperationException { //CubesSecurity.checkSetCubes(); if (cubesClient != null) { this.cubesClient = cubesClient; Log.debug("Client set"); setupClient.set(true); } else { this.cubesClient = null; Log.debug("Client set to null"); setupClient.set(false); } } @Override public void resize(int width, int height) { if (width == 0 || height == 0) return; try { Graphics.resize(width, height); if (menu != null) menu.resize(Graphics.GUI_WIDTH, Graphics.GUI_HEIGHT); if (cubesClient != null) cubesClient.resize(Graphics.RENDER_WIDTH, Graphics.RENDER_HEIGHT); } catch (StopLoopException e) { Log.debug(e); } catch (Exception e) { Debug.crash(e); } } @Override public void setServer(CubesServer cubesServer) throws UnsupportedOperationException { //CubesSecurity.checkSetCubes(); if (cubesServer != null) { if (cubesServer instanceof IntegratedServer) { this.cubesServer = (IntegratedServer) cubesServer; Log.debug("Server set"); this.cubesServer.start(); } else { throw new CubesException("Server can only be set to an IntegratedServer"); } } else { this.cubesServer = null; Log.debug("Server set to null"); } } private boolean splashScreen() { Log.debug("Showing splash screen"); glClear(); SplashMenu splashMenu = new SplashMenu(); Graphics.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); splashMenu.resize(Graphics.GUI_WIDTH, Graphics.GUI_HEIGHT); splashMenu.render(); Log.debug("Splash screen rendered"); return true; } private boolean initCubes() { Cubes.init(); if (options.loadTemporaryWorld) { Log.info(Localization.get("client.load_temporary_world")); Adapter.setMenu(new SingleplayerLoadingMenu(ClientSaveManager.createTemporarySave("core:smooth", Gamemode.creative, ""))); } else { setMenu(new MainMenu()); Log.info(Localization.get("client.client_loaded")); } return true; } @Override public void render() { if (shownSplash.compareAndSet(false, true) && splashScreen()) return; if (setupCubes.compareAndSet(false, true) && initCubes()) return; try { if (cubesClient == null && menu == null) { //Nothing to render Debug.crash(new CubesException("CubesClient and Menu both null")); } boolean takeScreenshot = Keybinds.isJustPressed(Keybinds.KEYBIND_SCREENSHOT); if (takeScreenshot) Screenshot.startScreenshot(); Compatibility.get().update(); glClear(); if (cubesClient != null) { if (setupClient.getAndSet(false)) { cubesClient.create(); cubesClient.resize(Graphics.RENDER_WIDTH, Graphics.RENDER_HEIGHT); } cubesClient.render(); } if (menu != null) { if (setupMenu.getAndSet(false)) { menu.resize(Graphics.GUI_WIDTH, Graphics.GUI_HEIGHT); InputChain.showMenu(menu); menu.show(); } if (menu.shouldRenderBackground()) MenuManager.renderBackground(); menu.render(); //Render menu over client } if (menu != null || (cubesClient != null && cubesClient.renderer != null && cubesClient.renderer.noCursorCatching())) { Gdx.input.setCursorCatched(false); } else { Gdx.input.setCursorCatched(true); } if (!Branding.IS_DEBUG && cubesClient != null && cubesServer != null && cubesServer.isRunning() && CubesServer.lastUpdateTime() + 2500 < System.currentTimeMillis()) { Log.error("Server is unresponsive"); Debug.printThreads(); Adapter.gotoMenu(new UnresponsiveIntegratedServerMenu()); } if (takeScreenshot) Screenshot.endScreenshot(); } catch (StopLoopException e) { Log.debug(e); } catch (Exception e) { Debug.crash(e); } } private void glClear() { try { Color skyColour = ((WorldClient) cubesClient.world).getSkyColour(); Gdx.gl20.glClearColor(skyColour.r, skyColour.g, skyColour.b, skyColour.a); } catch (Exception ignored) { Gdx.gl20.glClearColor(0, 0, 0, 1f); } Gdx.gl20.glViewport(0, 0, Graphics.RENDER_WIDTH, Graphics.RENDER_HEIGHT); Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); } @Override public void setMenu(Menu menu) { //CubesSecurity.checkSetMenu(); Menu old = this.menu; if (old != null) { old.hide(); InputChain.hideMenu(old); } this.menu = menu; if (menu != null) { Log.debug("Menu set to " + menu.getClass().getSimpleName()); MenuManager.setMenu(menu); setupMenu.set(true); } else { Log.debug("Menu set to null"); setupMenu.set(false); } } @Override public void pause() { try { if (cubesClient != null) cubesClient.pause(); } catch (StopLoopException e) { Log.debug(e); } catch (Exception e) { Debug.crash(e); } } @Override public CubesClient getClient() { return cubesClient; } @Override public void resume() { try { if (cubesClient != null) cubesClient.resume(); } catch (StopLoopException e) { Log.debug(e); } catch (Exception e) { Debug.crash(e); } } @Override public CubesServer getServer() { return cubesServer; } @Override public Menu getMenu() { return menu; } @Override public Side getSide() { return Side.Client; } @Override public void dispose() { try { Adapter.dispose(); } catch (StopLoopException ignored) { } } @Override public Thread getThread() { return thread; } }