Skip to content

Commit

Permalink
Support secondary TCP connections (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
beverly-hills-money-gangster authored Jul 19, 2024
1 parent c925466 commit 9d3a87e
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 101 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ gradle desktop:dist
To turn dev mode on, please run the game with `DESKTOP_DEV_MODE=true` environment variable. Dev mode features:
- Smaller window size, so you can run multiple game windows at the same time and see IDE logs on-fly
- Cursor gets "un-caught" when "Esc" is pressed during death-match, so you can use the mouse to go back to IDE or run one more game window
- Basic network metrics are rendered on the screen during death-match

#### Debug controls
- N - see network metrics
- P - log current player position

## Distribution

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ project(":core") {
implementation 'commons-io:commons-io:2.8.0'
api 'org.apache.commons:commons-lang3:3.13.0'
api 'ch.qos.logback:logback-classic:1.4.12'
api "com.github.beverly-hills-money-gangster.Daikombat-server:net-client:8.0.2"
api "com.github.beverly-hills-money-gangster.Daikombat-server:net-client:9f29c6360b"
api 'commons-validator:commons-validator:1.7'
api 'org.apache.commons:commons-math3:3.6.1'
compileOnly 'org.projectlombok:lombok:1.18.30'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public void getHit() {
}

protected long getAnimationTimeoutMls() {
return System.currentTimeMillis() + 100;
return System.currentTimeMillis() + 150;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@
import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.beverly.hills.money.gang.Configs;
import com.beverly.hills.money.gang.Constants;
import com.beverly.hills.money.gang.assets.managers.registry.TexturesRegistry;
import com.beverly.hills.money.gang.entities.player.Player;
import com.beverly.hills.money.gang.models.ModelInstanceBB;
import com.beverly.hills.money.gang.rect.RectanglePlus;
import com.beverly.hills.money.gang.rect.filters.RectanglePlusFilter;
import com.beverly.hills.money.gang.screens.GameScreen;
import com.beverly.hills.money.gang.screens.ui.selection.SkinUISelection;
import java.util.ArrayDeque;
import java.util.Queue;
import lombok.Getter;
Expand All @@ -33,6 +31,8 @@ public class EnemyPlayer extends Enemy {

private final EnemyTextures enemyTextures;

private int lastEventSequenceId = -1;

private static final int MAX_ACTION_QUEUE_CLOGGING = 30;

private final Queue<EnemyPlayerAction> actions = new ArrayDeque<>();
Expand Down Expand Up @@ -93,20 +93,43 @@ public void queueAction(EnemyPlayerAction enemyPlayerAction) {
} else {
this.currentSpeed = getSpeed(actions, this.defaultSpeed);
}
actions.add(enemyPlayerAction);
}

// if in order
if (enemyPlayerAction.getEventSequenceId() > lastEventSequenceId) {
lastEventSequenceId = enemyPlayerAction.getEventSequenceId();
actions.add(enemyPlayerAction);
return;
}

// fix out-of-order case
switch (enemyPlayerAction.getEnemyPlayerActionType()) {
case MOVE -> LOG.warn(
"MOVE event is out of order. Last event sequence id {} but given {}. Skip event.",
lastEventSequenceId, enemyPlayerAction.getEventSequenceId());
case SHOOT, PUNCH -> {
LOG.warn(
"SHOOT/PUNCH event is out of order. Last event sequence id {} but given {}",
lastEventSequenceId, enemyPlayerAction.getEventSequenceId());
actions.add(EnemyPlayerAction.builder()
.enemyPlayerActionType(enemyPlayerAction.getEnemyPlayerActionType())
.eventSequenceId(enemyPlayerAction.getEventSequenceId())
.onComplete(enemyPlayerAction.getOnComplete())
.direction(enemyPlayerAction.getDirection())
.route(getRect().getOldPosition())
.build());
}
}
}

static float getSpeed(final Queue<EnemyPlayerAction> actions, final float defaultSpeed) {
if (actions.size() > 15) {
LOG.info("Action queue is super clogged. Size {}", actions.size());
return defaultSpeed * 3f;
LOG.warn("Action queue is super clogged. Size {}", actions.size());
return defaultSpeed * 3f;
} else if (actions.size() > 10) {
LOG.info("Action queue is very clogged. Size {}", actions.size());
LOG.warn("Action queue is very clogged. Size {}", actions.size());
return defaultSpeed * 2f;
} else if (actions.size() >= 5) {
LOG.info("Action queue is clogged. Size {}", actions.size());
LOG.warn("Action queue is clogged. Size {}", actions.size());
return defaultSpeed * 1.25f;
} else if (actions.size() > 2) {
return defaultSpeed * 1.15f;
Expand All @@ -130,7 +153,7 @@ public void render3D(final ModelBatch mdlBatch, final Environment env, final flo
getMdlInst().transform.setToLookAt(
getScreen().getCurrentCam().direction.cpy().rotate(Vector3.Z, 180f), Vector3.Y);
getMdlInst().transform.setTranslation(getPosition().cpy().add(0, Constants.HALF_UNIT, 0));
// otherwise, it the enemy is too "fat"
// otherwise, the enemy is too "fat"
getMdlInst().transform.scale(0.8f, 1f, 1);
super.render3D(mdlBatch, env, delta);
}
Expand Down Expand Up @@ -169,7 +192,7 @@ public void tick(final float delta) {
}

}
} else {
} else if (System.currentTimeMillis() >= movingAnimationUntil) {
isIdle = true;
}
getRect().setX(getRect().getNewPosition().x);
Expand Down Expand Up @@ -198,41 +221,41 @@ private TextureRegion getTextureToUse() {
float angle = playerDirection.angleDeg(lastDirection);

if (Constants.FRONT_RANGE.contains(angle)) {
if (keepShootingAnimation()) {
if (isShootingAnimation()) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.SHOOTINGTEXFRONTREG);
} else if (isIdle) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.IDLETEXFRONTREG);
} else if (keepMovingAnimation()) {
} else if (isNextStepAnimation()) {
movingAnimationUntil = getAnimationTimeoutMls();
currentStep++;
return enemyTextures.getEnemyPlayerMoveFrontTextureRegion(currentStep);
}
} else if (Constants.LEFT_RANGE.contains(angle)) {
if (keepShootingAnimation()) {
if (isShootingAnimation()) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.SHOOTINGTEXLEFTREG);
} else if (isIdle) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.IDLETEXLEFTREG);
} else if (keepMovingAnimation()) {
} else if (isNextStepAnimation()) {
movingAnimationUntil = getAnimationTimeoutMls();
currentStep++;
return enemyTextures.getEnemyPlayerMoveLeftTextureRegion(currentStep);
}
} else if (Constants.RIGHT_RANGE.contains(angle)) {
if (keepShootingAnimation()) {
if (isShootingAnimation()) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.SHOOTINGTEXRIGHTREG);
} else if (isIdle) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.IDLETEXRIGHTREG);
} else if (keepMovingAnimation()) {
} else if (isNextStepAnimation()) {
movingAnimationUntil = getAnimationTimeoutMls();
currentStep++;
return enemyTextures.getEnemyPlayerMoveRightTextureRegion(currentStep);
}
} else {
if (keepShootingAnimation()) {
if (isShootingAnimation()) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.SHOOTINGTEXBACKTREG);
} else if (isIdle) {
return enemyTextures.getEnemyPlayerTextureRegion(EnemyTextureRegistry.IDLETEXBACKREG);
} else if (keepMovingAnimation()) {
} else if (isNextStepAnimation()) {
movingAnimationUntil = getAnimationTimeoutMls();
currentStep += 1;
return enemyTextures.getEnemyPlayerMoveBackTextureRegion(currentStep);
Expand All @@ -241,11 +264,11 @@ private TextureRegion getTextureToUse() {
return null;
}

private boolean keepShootingAnimation() {
private boolean isShootingAnimation() {
return System.currentTimeMillis() <= shootingAnimationUntil;
}

private boolean keepMovingAnimation() {
private boolean isNextStepAnimation() {
return System.currentTimeMillis() >= movingAnimationUntil;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Getter;
import lombok.NonNull;

@Getter
@Builder
Expand All @@ -12,6 +13,8 @@ public class EnemyPlayerAction {
private final Vector2 route;
private final Vector2 direction;
private final EnemyPlayerActionType enemyPlayerActionType;
@NonNull
private final Integer eventSequenceId;
@Default
private final Runnable onComplete = () -> {
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.beverly.hills.money.gang.entities.ui;

import com.beverly.hills.money.gang.stats.NetworkStatsReader;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.FileUtils;

@RequiredArgsConstructor
public class UINetworkStats {

private final NetworkStatsReader primaryNetworkStats;
private final Iterable<NetworkStatsReader> secondaryNetworkStats;

private String networkStatsToString(int receivedMsg, int sentMsg, long inboundBytes,
long outboundBytes, Integer pingMls) {
return String.format(Locale.ENGLISH,
"RCV %s MSG | SENT %s MSG | IN %s | OUT %s | PING %s MS",
receivedMsg,
sentMsg,
FileUtils.byteCountToDisplaySize(inboundBytes),
FileUtils.byteCountToDisplaySize(outboundBytes),
Objects.toString(pingMls, "-"))
.toUpperCase();
}

private String networkStatsToString(NetworkStatsReader networkStatsReader) {
return networkStatsToString(networkStatsReader.getReceivedMessages(),
networkStatsReader.getSentMessages(), networkStatsReader.getInboundPayloadBytes(),
networkStatsReader.getOutboundPayloadBytes(), networkStatsReader.getPingMls());
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
int totalReceivedMsg = primaryNetworkStats.getReceivedMessages();
int totalSentMsg = primaryNetworkStats.getSentMessages();
long totalInboundBytes = primaryNetworkStats.getInboundPayloadBytes();
long totalOutboundBytes = primaryNetworkStats.getOutboundPayloadBytes();
sb.append("PRIMARY ").append(networkStatsToString(primaryNetworkStats)).append("\n");
int totalPing = Optional.ofNullable(primaryNetworkStats.getPingMls()).orElse(0);
int totalConnections = 1;
for (NetworkStatsReader networkStatsReader : secondaryNetworkStats) {
sb.append("SECONDARY ").append(networkStatsToString(networkStatsReader))
.append("\n");
totalReceivedMsg += networkStatsReader.getReceivedMessages();
totalSentMsg += networkStatsReader.getSentMessages();
totalInboundBytes += networkStatsReader.getInboundPayloadBytes();
totalOutboundBytes += networkStatsReader.getOutboundPayloadBytes();
totalPing += Optional.ofNullable(networkStatsReader.getPingMls()).orElse(0);
totalConnections++;
}
sb.append("TOTAL ").append(
networkStatsToString(totalReceivedMsg, totalSentMsg, totalInboundBytes, totalOutboundBytes,
totalPing / totalConnections))
.append("\n");
return sb.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ public class PlayScreenGameConnectionHandler {

private static final Logger LOG = LoggerFactory.getLogger(PlayScreenGameConnectionHandler.class);

private static final int EVENTS_TO_POLL = 10;

private final PlayScreen playScreen;

private boolean initialRequestHandled;
Expand All @@ -44,7 +42,8 @@ public void handle() {
LOG.info("Stop handling");
return;
}
playScreen.getGameConnection().getResponse().poll(EVENTS_TO_POLL).forEach(serverResponse -> {
// TODO sort game responses
playScreen.getGameConnection().pollResponses().forEach(serverResponse -> {
if (serverResponse.hasChatEvents()) {
handleChat(serverResponse.getChatEvents());
} else if (serverResponse.hasGameEvents()) {
Expand All @@ -57,9 +56,7 @@ public void handle() {
handlePowerUpSpawn(serverResponse.getPowerUpSpawn());
}
});

playScreen.getGameConnection().getErrors().poll()
.ifPresent(this::handleException);
playScreen.getGameConnection().pollErrors().forEach(this::handleException);
if (!initialRequestHandled) {
initialRequestHandled = true;
}
Expand Down Expand Up @@ -107,6 +104,7 @@ private void handleSpawn(ServerResponse.GameEvent gameEvent) {
LOG.info("Player already spawned {}", gameEvent);
return;
}
LOG.info("Spawn player {}", gameEvent.getPlayer().getPlayerName());
EnemyPlayer enemyPlayer = new EnemyPlayer(playScreen.getPlayer(),
gameEvent.getPlayer().getPlayerId(),
new Vector3(gameEvent.getPlayer().getPosition().getX(),
Expand Down Expand Up @@ -179,6 +177,7 @@ private void handleMove(ServerResponse.GameEvent gameEvent) {
gameEvent.getPlayer().getActivePowerUpsList().forEach(gamePowerUp
-> activateEnemyPowerUp(enemyPlayer, gamePowerUp));
enemyPlayer.queueAction(EnemyPlayerAction.builder()
.eventSequenceId(gameEvent.getSequence())
.enemyPlayerActionType(EnemyPlayerActionType.MOVE)
.direction(Converter.convertToVector2(gameEvent.getPlayer().getDirection()))
.route(Converter.convertToVector2(gameEvent.getPlayer().getPosition())).build());
Expand Down Expand Up @@ -236,6 +235,7 @@ private void handleAttackMiss(ServerResponse.GameEvent gameEvent) {
};
enemiesRegistry.getEnemy(gameEvent.getPlayer().getPlayerId())
.ifPresent(enemyPlayer -> enemyPlayer.queueAction(EnemyPlayerAction.builder()
.eventSequenceId(gameEvent.getSequence())
.enemyPlayerActionType(enemyPlayerActionType)
.direction(Converter.convertToVector2(gameEvent.getPlayer().getDirection()))
.route(Converter.convertToVector2(gameEvent.getPlayer().getPosition())).build()));
Expand All @@ -258,6 +258,7 @@ private void handleGetHit(ServerResponse.GameEvent gameEvent) {
enemiesRegistry.getEnemy(gameEvent.getPlayer().getPlayerId())
.ifPresent(enemyPlayer -> {
enemyPlayer.queueAction(EnemyPlayerAction.builder()
.eventSequenceId(gameEvent.getSequence())
.enemyPlayerActionType(enemyPlayerActionType)
.direction(Converter.convertToVector2(gameEvent.getPlayer().getDirection()))
.route(Converter.convertToVector2(gameEvent.getPlayer().getPosition()))
Expand All @@ -274,6 +275,7 @@ private void handleGetHit(ServerResponse.GameEvent gameEvent) {
// enemies hitting each other
enemiesRegistry.getEnemy(gameEvent.getPlayer().getPlayerId())
.ifPresent(enemyPlayer -> enemyPlayer.queueAction(EnemyPlayerAction.builder()
.eventSequenceId(gameEvent.getSequence())
.enemyPlayerActionType(enemyPlayerActionType)
.direction(Converter.convertToVector2(gameEvent.getPlayer().getDirection()))
.route(Converter.convertToVector2(gameEvent.getPlayer().getPosition()))
Expand Down Expand Up @@ -304,6 +306,7 @@ private void handleDeath(ServerResponse.GameEvent gameEvent) {

enemiesRegistry.getEnemy(gameEvent.getPlayer().getPlayerId())
.ifPresent(enemyPlayer -> enemyPlayer.queueAction(EnemyPlayerAction.builder()
.eventSequenceId(gameEvent.getSequence())
.enemyPlayerActionType(enemyPlayerActionType)
.direction(Converter.convertToVector2(gameEvent.getPlayer().getDirection()))
.route(Converter.convertToVector2(gameEvent.getPlayer().getPosition()))
Expand Down Expand Up @@ -340,6 +343,7 @@ private void handleDeath(ServerResponse.GameEvent gameEvent) {
} else {
enemiesRegistry.getEnemy(gameEvent.getPlayer().getPlayerId())
.ifPresent(enemyPlayer -> enemyPlayer.queueAction(EnemyPlayerAction.builder()
.eventSequenceId(gameEvent.getSequence())
.enemyPlayerActionType(enemyPlayerActionType)
.direction(Converter.convertToVector2(gameEvent.getPlayer().getDirection()))
.route(Converter.convertToVector2(gameEvent.getPlayer().getPosition()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
import com.beverly.hills.money.gang.DaiKombatGame;
import com.beverly.hills.money.gang.assets.managers.registry.FontRegistry;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ErrorScreen extends AbstractMainMenuScreen {

private static final Logger LOG = LoggerFactory.getLogger(JoinGameScreen.class);

private final String errorMessage;
private final BitmapFont guiFont32;
Expand All @@ -20,6 +23,7 @@ public class ErrorScreen extends AbstractMainMenuScreen {
public ErrorScreen(final DaiKombatGame game, final String errorMessage) {
super(game);
this.errorMessage = errorMessage.toUpperCase(Locale.ENGLISH);
LOG.error("Go to error screen with error '{}'", errorMessage);
guiFont32 = game.getAssMan().getFont(FontRegistry.FONT_32);
guiFont64 = game.getAssMan().getFont(FontRegistry.FONT_64);
}
Expand Down
Loading

0 comments on commit 9d3a87e

Please sign in to comment.