public void run() throws InterruptedException, IOException { GameInitializer.initializeDisplay(); Textures.initializeTextures(); Crissaegrim.initializePlayer(boardMap); Player player = Crissaegrim.getPlayer(); EntityMovementHelper playerMovementHelper = player.getMovementHelper(); Crissaegrim.getValmanwayConnection().connectToValmonwayServer(); if (Crissaegrim.connectionStable) { // Wait to get player id... long lastSend = 0; while (player.getId() == -1) { if (Thunderbrand.getTime() - lastSend > Crissaegrim.getValmanwayConnection().getConnectionTimeoutMillis()) { lastSend = Thunderbrand.getTime(); Crissaegrim.addOutgoingDataPacket( new RequestPlayerIdPacket(Crissaegrim.getClientVersion())); } } } else { // Couldn't connect + offline mode disallowed; display error and quit displayMessageForever(Textures.NO_CONNECTION_MESSAGE, 458, 64, null); return; } if (player.getId() == -2) { // playerId of -2 signifies outdated version displayMessageForever( Textures.CLIENT_OUTDATED_MESSAGE, 595, 102, "Your version is outdated!"); return; } Crissaegrim.addSystemMessage("Welcome to Crissaegrim!"); setNewDestinationToSpawn(); requestTravelToDestinationBoard(); // Set name to last used username if applicable: String lastUsername = Crissaegrim.getPreferenceHandler().getLastUsername(); if (lastUsername != null) { Crissaegrim.addOutgoingDataPacket( new SendChatMessagePacket(new TextBlock("/setname " + lastUsername, Color.WHITE))); } else { Crissaegrim.addSystemMessage("Tip: You can use /setname to permanently set your username."); } // initializeGame(); lastFPSTitleUpdate = Thunderbrand.getTime(); GameInitializer.initializeOpenGLFor2D(); long startTime, endTime, elaspedTime; // Per-loop times to keep FRAMES_PER_SECOND while (!Display.isCloseRequested()) { startTime = Thunderbrand.getTime(); if (!Crissaegrim.connectionStable) { // Lost connection to server Crissaegrim.getValmanwayConnection().closeConnections(); displayMessageForever( Textures.LOST_CONNECTION_MESSAGE, 423, 64, "Connection lost - Please restart"); return; } // Update the board, including all entities and bullets: if (!Crissaegrim.currentlyLoading) { ClientBoard.verifyChunksExist(Crissaegrim.getCurrentBoard()); if (Crissaegrim.currentlyLoading) { continue; } player.update(); setIconForDoodads(); setIconForLocalDroppedItems(); // Draw new scene: drawScene(); // Get input and move the player: if (Crissaegrim.getChatBox().isTypingMode()) { Crissaegrim.getChatBox().getKeyboardInput(true); } else { getKeyboardAndMouseInput(); } drawMouseHoverStatus(); playerMovementHelper.moveEntityPre(); Item itemToUse = playerMovementHelper.getItemToUse(); if (itemToUse != null && !player.isBusy()) { // Cycle through relevant click-to-interact Doodads: for (Doodad doodad : Crissaegrim.getCurrentBoard().getDoodads().values()) { if (!player.isBusy() && RectUtils.coordinateIsInRect(player.getPosition(), doodad.getBounds())) { switch (doodad.getDoodadAction()) { case DoodadActions.MINE_ROCK: if (!(player.getInventory().getCurrentItem() instanceof ItemPickaxe)) { Crissaegrim.addSystemMessage( "You need to be holding a pickaxe to mine this rock."); } else if (player.getInventory().isFull()) { new DialogBoxRunner().run(new DialogBox("Your inventory is full.", "Ok")); } else { MineableRock mineableRock = (MineableRock) doodad; ItemPickaxe pickaxe = (ItemPickaxe) (player.getInventory().getCurrentItem()); if (!mineableRock.isDepleted()) { Crissaegrim.addSystemMessage("You start mining the rock..."); player.setBusy( new MiningRockBusy(player.getPosition(), pickaxe.getPickaxeType())); Crissaegrim.addOutgoingDataPacket( new MineRockRequestPacket( mineableRock.getId(), player.getId(), player.getBusy().getId(), player.getCurrentBoardName(), mineableRock.getChanceOfSuccess() * pickaxe.getChanceOfSuccessMultiplier())); } } break; default: break; } break; // Found the relevant Doodad; ignore the rest } } // Use item if necessary: if (itemToUse instanceof ItemSword) { // TODO: This should be split up depending upon the weapon and attack type // TODO: Bounding rect of sword swing should not be entire entity ItemSword sword = (ItemSword) (itemToUse); player.setBusy(new SwordSwingBusy(sword.getSwordType())); Crissaegrim.addOutgoingDataPacket( new AttackPacket( new Attack( player.getId(), player.getCurrentBoardName(), player.getSwordSwingRect(sword), sword.getAttackPower(), 1))); } else if (itemToUse instanceof ItemPartyPopper) { ItemPartyPopper popper = (ItemPartyPopper) (itemToUse); Crissaegrim.addOutgoingDataPacket( new ParticleSystemPacket( 125, playerMovementHelper.getCoordinateClicked(), player.getCurrentBoardName(), popper.getColor())); if (popper.removeOneFromStack()) { player.getInventory().removeCurrentItem(); } } } playerMovementHelper.moveEntityPost(); drawHUD(); // Transmit data to the server Crissaegrim.getValmanwayConnection().sendPlayerStatus(); } else { drawScene(); drawLoadingMessage(); drawLoadingProgressBar(); } Display.update(); endTime = Thunderbrand.getTime(); elaspedTime = endTime - startTime; Thread.sleep(Math.max(0, MILLISECONDS_PER_FRAME - elaspedTime)); updateFPS(Math.max(0, MILLISECONDS_PER_FRAME - elaspedTime)); } Display.destroy(); Crissaegrim.getValmanwayConnection().closeConnections(); }
/** Detects keyboard and mouse input and makes the main player react accordingly. */ private void getKeyboardAndMouseInput() { Player player = Crissaegrim.getPlayer(); EntityMovementHelper pmh = player.getMovementHelper(); if (Keyboard.isKeyDown(Keyboard.KEY_A)) { pmh.requestLeftMovement(); } if (Keyboard.isKeyDown(Keyboard.KEY_D)) { pmh.requestRightMovement(); } if (Keyboard.isKeyDown(Keyboard.KEY_W) || Keyboard.isKeyDown(Keyboard.KEY_SPACE)) { pmh.requestJumpMovement(); } while (Keyboard.next()) { if (Keyboard.getEventKeyState()) { // Key was pressed (not released) int pressedKey = Keyboard.getEventKey(); // if (pressedKey == Keyboard.KEY_B) { // DialogBoxRunner dbr = new DialogBoxRunner(); // DialogBox.Result res = dbr.run(new DialogBox( // Arrays.asList("A wild dialog box appeared!", "Do you want to set this location as // your respawn point?"), // Arrays.asList("Yes", "No", "I-I don't know, I thought I heard a thump?"))); // if (res == DialogBox.Result.BUTTON_1) { Crissaegrim.addSystemMessage("Cool."); } // else if (res == DialogBox.Result.BUTTON_2) { Crissaegrim.addSystemMessage("Fine!"); } // else if (res == DialogBox.Result.BUTTON_3) { // Crissaegrim.addSystemMessage("P-President Fabio?"); } // } // if (pressedKey == Keyboard.KEY_B) { // new SmithingRunner().run(); // Incomplete // } if (pressedKey == Keyboard.KEY_B) { player.receiveItem(Items.tameikeSword()); player.receiveItem(Items.tameikePickaxe()); player.receiveItem(Items.bluePartyPopper()); } if (pressedKey == Keyboard.KEY_T || pressedKey == Keyboard.KEY_RETURN) { // T or Enter: Enter chat mode Crissaegrim.getChatBox().enableTypingMode(); return; // Don't process any more keys! } else if (pressedKey == Keyboard.KEY_UP) { // Up arrow: Select previous inventory item player.getInventory().selectPreviousItem(); } else if (pressedKey == Keyboard.KEY_DOWN) { // Down arrow: Select next inventory item player.getInventory().selectNextItem(); } else if (pressedKey >= Keyboard.KEY_1 && pressedKey <= Keyboard.KEY_8) { // 1-8: Select inventory item player.getInventory().selectSpecificItem(pressedKey - Keyboard.KEY_1); } else if (pressedKey == 41) { // Backtick (`) key Crissaegrim.toggleDebugMode(); } else if (pressedKey == Keyboard.KEY_TAB) { // Tab key: Toggle zoom Crissaegrim.toggleZoom(); } else if (pressedKey == Keyboard.KEY_M) { // M key: Toggle window size Crissaegrim.toggleWindowSize(); } else if (pressedKey == Keyboard.KEY_E) { // E key: Open inventory new InventoryRunner().run(); } else if (pressedKey == Keyboard.KEY_F) { // F key: Activate F-key doodads or pick up items boolean pickedUpAnItem = false; Iterator<LocalDroppedItem> localDroppedItemsIter = localDroppedItems.iterator(); while (localDroppedItemsIter.hasNext()) { LocalDroppedItem localDroppedItem = localDroppedItemsIter.next(); if (!player.isBusy() && player.getCurrentBoardName().equals(localDroppedItem.getBoardName()) && RectUtils.rectsOverlap( Crissaegrim.getPlayer().getEntityEntireRect(), localDroppedItem.getBounds())) { if (player.getInventory().isFull()) { Crissaegrim.addSystemMessage("Your inventory is full."); } else { Item item = localDroppedItem.getItem(); if (item instanceof StackableItem) { Crissaegrim.addSystemMessage( "You picked up " + ((StackableItem) (item)).getNumberInStack() + " " + item.getName() + "s."); } else { Crissaegrim.addSystemMessage( "You picked up " + TextUtils.aOrAn(item.getName()) + " " + item.getName() + "."); } player.getInventory().addItem(item); localDroppedItemsIter.remove(); pickedUpAnItem = true; } break; } } if (!pickedUpAnItem) { // If the F key was not used to pick up an item, it will be used to // activate a doodad for (Doodad doodad : Crissaegrim.getCurrentBoard().getDoodads().values()) { if (!player.isBusy() && RectUtils.coordinateIsInRect(player.getPosition(), doodad.getBounds())) { switch (doodad.getDoodadAction()) { case DoodadActions.GO_THROUGH_DOORWAY: Door door = (Door) doodad; pmh.resetMovementRequests(); setNewDestination( door.getDestinationBoardName(), door.getDestinationCoordinate()); requestTravelToDestinationBoard(); break; case DoodadActions.SMELT_ORE: new SmeltingRunner().run(); break; case DoodadActions.READ_SIGNPOST: Signpost signpost = (Signpost) doodad; new DialogBoxRunner().run(new DialogBox(signpost.getMessages(), "Ok")); break; default: break; } break; // Found the relevant Doodad; ignore the rest } } } } } } if (!Crissaegrim.getChatBox().isTypingMode()) { while (Mouse.next()) { if (Mouse.getEventButtonState()) { // Button was clicked (not released) if (Mouse.getEventButton() == 0) { pmh.requestUseItem( getCoordinatesForMouse(), Crissaegrim.getPlayer().getInventory().getCurrentItem()); } } } int scrollDelta = Mouse.getDWheel(); if (scrollDelta < 0) { Crissaegrim.getPlayer().getInventory().selectNextItem(); } else if (scrollDelta > 0) { Crissaegrim.getPlayer().getInventory().selectPreviousItem(); } } }