Skip to content

Commit

Permalink
client-client networking
Browse files Browse the repository at this point in the history
  • Loading branch information
WMF-Industries committed Feb 26, 2024
1 parent c386354 commit d723918
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 41 deletions.
10 changes: 9 additions & 1 deletion assets/bundles/bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ setting.wdtg-mode.name = Disable Enemies
setting.wdtg-mode.description = Disables enemy unit factories, kills existing enemy units every refresh
setting.wdtg-buttons.name = Enable Capturing
setting.wdtg-buttons.description = Shows buttons to capture enemy content
setting.wdtg-direct.name = Allow Direct Execution
setting.wdtg-direct.description = Allows players with admin to use capture without validation by host

wdtg-cap-unit = Capture Units
wdtg-cap-block = Capture Blocks
Expand All @@ -21,17 +23,23 @@ wdtg-team-selector = Team Selector
wdtg-dialog = Select Team
wdtg-dialog-override = Override Settings

# These words are used to build the sentence on runtime
# Translate them as a whole sentence (to get the context right)
wdtg-capture-message = Captured
wdtg-capture-message-blocks = Buildings
wdtg-capture-message-and = And
wdtg-capture-message-units = Units
wdtg-capture-message-from = From
wdtg-capture-message-extra = All Teams
wdtg-capture-message-empty = Nothing to capture...
# <player> Requests To Capture <option> <wdtg-capture-message-from> <team>
wdtg-capture-request = Requests To Capture
wdtg-capture-request-sent = Sent capture request to the host!
wdtg-capture-request-warn = Missing Permissions!
wdtg-select-message = Currently Selected:
wdtg-select-message-any = <Any>

wdtg-client-warn = You aren't the host, u moron :3
wdtg-vanilla-host-warn = The host does not appear to have the mod!
wdtg-pvp-warn = PvP detected\nUnfair Features disabled!


2 changes: 1 addition & 1 deletion assets/mod.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: "wdtg"
author: "WMF Industries & RushieWashie"
main: "wheredidtheygo.wheredidtheygo"
description: "Enemy units do not exist!"
version: "1.3"
version: "1.4"
minGameVersion: 145
java: true
hidden: true
146 changes: 113 additions & 33 deletions src/wheredidtheygo/ui/GlobalConfig.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package wheredidtheygo.ui;

import arc.*;
import arc.graphics.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
Expand All @@ -18,10 +17,13 @@ public class GlobalConfig{
public Table mapTable = new Table(), teamsTable = new Table(), textTable = new Table(), overrideTable = new Table();
public BaseDialog teamSelect = new BaseDialog(Core.bundle.get("wdtg-dialog")),
overrides = new BaseDialog(Core.bundle.get("wdtg-dialog-override"));
public Team selectedTeam = Team.derelict, captureTeam;
String data;
public Team selectedTeam = Team.derelict, captureTeam, paramTeam;
String data, playerName, capUnit, capBlock, capAll, teamSelector,
msgCap, msgBuild, msgUnit, msgAnd, msgFrom, msgTeams, msgEmpty,
msgSelect, msgAny, msgReq, msgSent, warnHost, warnPvp, warnPerms;
Seq<Teams.TeamData> teamCache = new Seq<>();
boolean stateCache, firstRun;
boolean stateCache, updateButtons, firstRun, validHost;
int count;

public GlobalConfig(){
ui.settings.addCategory(Core.bundle.get("wdtg-category"), Icon.box, t ->{
Expand All @@ -33,6 +35,7 @@ public GlobalConfig(){
subTable.checkPref("wdtg-mode", true);
subTable.sliderPref("wdtg-refresh-rate", 1, 1, 10, 1, s -> s + Strings.format(" time@ per second", s > 1 ? "s" : ""));
subTable.checkPref("wdtg-buttons", true);
subTable.checkPref("wdtg-direct", false);

t.add(subTable);
});
Expand All @@ -41,43 +44,108 @@ public GlobalConfig(){
teamSelect.cont.center().top().add(textTable);
teamSelect.buttons.center().bottom().row().add(teamsTable);

netClient.addPacketHandler("wdtg-true", p -> validHost = true);
netServer.addPacketHandler("wdtg-check", (p, s) -> Call.clientPacketReliable(p.con(), "wdtg-true", ""));
netServer.addPacketHandler("wdtg-req", (p, s) -> {
String[] params = s.split(" ");
playerName = p.coloredName();
boolean multi = params[0].equals("true"), alternate = params[1].equals("true");
if(!params[2].equals("derelict")){
state.teams.present.each(t -> {
if (t.team.name.equals(params[2])) paramTeam = t.team;
});
}else paramTeam = Team.derelict;

if(Core.settings.getBool("wdtg-direct") && p.admin()){
capture(multi, alternate, true, paramTeam);
}else{
StringBuilder build = new StringBuilder();
String name = paramTeam.coloredName().isEmpty() ? getName(paramTeam) : paramTeam.coloredName();

build.append(playerName).append("[] ").append(msgReq).append(" ");
build.append(alternate ? msgBuild : msgUnit).append(" ");
if(multi) build.append(msgAnd).append(" ").append(!alternate ? msgBuild : msgUnit).append(" ");
build.append(msgFrom).append(" ").append(paramTeam == Team.derelict ? msgTeams : name);

ui.hudfrag.showToast(Icon.players, build.toString());

build.setLength(0);
playerName = "";
}
});

Events.on(EventType.WorldLoadEvent.class, e -> {
validHost = false;
if(net.client()) Call.serverPacketReliable("wdtg-check", "");

selectedTeam = Team.derelict;
teamCache.clear();
firstRun = true;
});

// load strings here and keep them in ram instead of looking through the bundle every single time
capUnit = Core.bundle.get("wdtg-cap-unit");
capBlock = Core.bundle.get("wdtg-cap-block");
capAll = Core.bundle.get("wdtg-cap-all");
teamSelector = Core.bundle.get("wdtg-team-selector");
msgCap = Core.bundle.get("wdtg-capture-message");
msgBuild = Core.bundle.get("wdtg-capture-message-blocks");
msgUnit = Core.bundle.get("wdtg-capture-message-units");
msgAnd = Core.bundle.get("wdtg-capture-message-and");
msgFrom = Core.bundle.get("wdtg-capture-message-from");
msgTeams = Core.bundle.get("wdtg-capture-message-extra");
msgEmpty = Core.bundle.get("wdtg-capture-message-empty");
msgSelect = Core.bundle.get("wdtg-select-message");
msgAny = Core.bundle.get("wdtg-select-message-any");
msgReq = Core.bundle.get("wdtg-capture-request");
msgSent = Core.bundle.get("wdtg-capture-request-sent");
warnHost = Core.bundle.get("wdtg-vanilla-host-warn");
warnPvp = Core.bundle.get("wdtg-pvp-warn");
warnPerms = Core.bundle.get("wdtg-capture-request-warn");
}

public void rebuildUis(boolean enabled){
if(valid(teamCache) && enabled == stateCache) return;
stateCache = enabled;

teamCache.clear();
teamCache.addAll(state.teams.present);
if(valid(teamCache)
&& enabled == stateCache
&& !updateButtons) return;

mapTable.reset();
mapTable.clear();

mapTable.visibility = () -> ui.minimapfrag.shown() && (enabled && !state.rules.pvp);
if(state.rules.pvp) ui.hudfrag.showToast(Icon.warning, "[scarlet]" + Core.bundle.get("wdtg-pvp-warn"));
if(state.rules.pvp) ui.hudfrag.showToast(Icon.infoCircle, "[scarlet]" + warnPvp);

mapTable.button(Core.bundle.get("wdtg-cap-unit"), Icon.units, Styles.squareTogglet, ()->{
mapTable.button(capUnit, Icon.units, Styles.squareTogglet, ()->{
capture(false, false, true, selectedTeam);
updateButtons = true;
}).width(180f).height(60f).margin(12f).checked(false).row();

mapTable.button(Core.bundle.get("wdtg-cap-block"), Icon.box, Styles.squareTogglet, ()->{
mapTable.button(capBlock, Icon.box, Styles.squareTogglet, ()->{
capture(false, true, true, selectedTeam);
updateButtons = true;
}).width(180f).height(60f).margin(12f).checked(false).row();

mapTable.button(Core.bundle.get("wdtg-cap-all"), Icon.list, Styles.squareTogglet, ()->{
mapTable.button(capAll, Icon.list, Styles.squareTogglet, ()->{
capture(true, false, true, selectedTeam);
updateButtons = true;
}).width(180f).height(60f).margin(12f).checked(false).row();

mapTable.button(Core.bundle.get("wdtg-team-selector"), Icon.settings, Styles.squareTogglet, ()->{
mapTable.button(teamSelector, Icon.settings, Styles.squareTogglet, ()->{
updateSelect();
teamSelect.show();
updateButtons = true;
}).width(180f).height(60f).margin(12f).checked(false).row();

if(updateButtons){
updateButtons = false;
return;
}

stateCache = enabled;

teamCache.clear();
teamCache.addAll(state.teams.present);

teamsTable.reset();
teamsTable.clear();

Expand All @@ -89,7 +157,7 @@ public void rebuildUis(boolean enabled){
state.teams.present.each(t -> {
if(t.team != player.team() && t.team != Team.derelict){
if(t.team.coloredName().isEmpty()){
data = color(t.team.color) + "#" + t.team.id;
data = getName(t.team);
}else{
data = t.team.coloredName();
}
Expand All @@ -106,12 +174,15 @@ private void updateSelect(){
textTable.reset();
textTable.clear();

textTable.add(Core.bundle.get("wdtg-select-message") + " " + (selectedTeam == Team.derelict ? Core.bundle.get("wdtg-select-message-any") : selectedTeam.coloredName()));
textTable.add(msgSelect + " " + (selectedTeam == Team.derelict ? msgAny : selectedTeam.coloredName()));
}

private void capture(boolean multi, boolean alternate, boolean notify, Team team){
if(net.client()){
ui.hudfrag.showToast("[scarlet]" + Core.bundle.get("wdtg-client-warn"));
if(validHost){
Call.serverPacketReliable("wdtg-req", Strings.format("@ @ @", multi, alternate, team));
ui.hudfrag.showToast(msgSent);
}else ui.hudfrag.showToast(Icon.cancel, "[scarlet]" + warnHost);
return;
}

Expand All @@ -123,20 +194,27 @@ private void capture(boolean multi, boolean alternate, boolean notify, Team team
Seq<Teams.TeamData> data = new Seq<>();
ObjectSet<Team> teams = new ObjectSet<>();
state.teams.present.each(t -> {
if(t.team != player.team() && (t.team == team || team == Team.derelict)){
count = 0;
t.buildings.each(b -> {
if(b.block().privileged && !b.block.targetable) ++count;
});
if(t.team != player.team() && (t.buildings.size > count
|| t.units.size != 0) && (t.team == team || team == Team.derelict)){
data.add(t);
teams.add(t.team);
}
});

if(data.isEmpty()){
ui.hudfrag.showToast("[yellow]" + Core.bundle.get("wdtg-capture-message-empty"));
if(notify) ui.hudfrag.showToast(Icon.warning, "[yellow]" + msgEmpty);
return;
}

if(multi || alternate){
Seq<Building> ret = new Seq<>();
data.each(t -> t.buildings.each(b -> {
if(b.block().privileged && !b.block.targetable) return;
// filter out world logic stuff

b.remove();
b.tile.setNet(b.block(), player.team(), b.rotation());

Expand All @@ -161,44 +239,46 @@ private void capture(boolean multi, boolean alternate, boolean notify, Team team

data.each(t -> {
// TODO: This will put heavy load on the cpu and might leak
if(t.buildings.size > 0) {
if(t.buildings.size > 0){
capture(multi, alternate, false, team);
}
});
}

if(multi || !alternate){
Groups.unit.each(u -> {
if(teams.contains(u.team())) u.team = player.team();
if(teams.contains(u.team())){
u.team = player.team();
u.resetController();
}
});
}

if(notify){
StringBuilder build = new StringBuilder();
String name = team.coloredName().isEmpty() ? color(team.color) + "#" + team.id : team.coloredName(),
capUnits = Core.bundle.get("wdtg-capture-message-units"), capBlocks = Core.bundle.get("wdtg-capture-message-blocks");
String name = team.coloredName().isEmpty() ? getName(team) : team.coloredName();

build.append(Core.bundle.get("wdtg-capture-message")).append(" ");
build.append(alternate ? capBlocks : capUnits).append(" ");
if(multi) build.append(Core.bundle.get("wdtg-capture-message-and")).append(" ").append(!alternate ? capBlocks : capUnits).append(" ");
build.append(Core.bundle.get("wdtg-capture-message-from")).append(" ");
if(!playerName.isEmpty()) build.append(playerName).append("[] ");
build.append(msgCap).append(" ").append(alternate ? msgBuild : msgUnit).append(" ");
if(multi) build.append(msgAnd).append(" ").append(!alternate ? msgBuild : msgUnit).append(" ");
build.append(msgFrom).append(" ").append(team == Team.derelict ? msgTeams : name).append("!");

ui.hudfrag.showToast(Strings.format("@" + "@!", build.toString(),
teams.size > 1 ? Core.bundle.get("wdtg-capture-message-extra") : name));
ui.hudfrag.showToast(build.toString());

build.setLength(0);
playerName = "";
}

data.clear();
teams.clear();
}

private String color(Color color){
return "[#" + color + "]";
private String getName(Team team){
return "[#" + team.color + "]#" + team.id;
}

private boolean valid(Seq<Teams.TeamData> seq){
if(seq.isEmpty()) return false;
if(seq.isEmpty() || seq.size != state.teams.present.size) return false;

ObjectSet<Team> teams = new ObjectSet<>();
state.teams.present.each(t -> teams.add(t.team));
Expand Down
26 changes: 20 additions & 6 deletions src/wheredidtheygo/wheredidtheygo.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
public class wheredidtheygo extends Mod{
public boolean loaded, teamExists, removeEnemies, enableCapturing,
affectWaves, showMenu, localOverride, temp1, temp2, temp3;
int refreshRate, waveOffset, temp;
int refreshRate, waveOffset, temp, count;
Team captureTeam;
public wheredidtheygo(){
Events.on(EventType.ClientLoadEvent.class, e -> {
Expand Down Expand Up @@ -78,7 +78,12 @@ public wheredidtheygo(){
Seq<Teams.TeamData> data = new Seq<>();
ObjectSet<Team> teams = new ObjectSet<>();
state.teams.present.each(t -> {
if(t.team != player.team() && (t.team.name.equalsIgnoreCase(args[2]) || args[2].isEmpty())){
count = 0;
t.buildings.each(b -> {
if(b.block().privileged && !b.block.targetable) ++count;
});
if(t.team != player.team() && (t.buildings.size > count
|| t.units.size != 0) && (t.team.name.equalsIgnoreCase(args[2]) || args[2].isEmpty())){
data.add(t);
teams.add(t.team);
if(t.team.name.equalsIgnoreCase(args[2])) teamExists = true;
Expand All @@ -95,15 +100,19 @@ public wheredidtheygo(){

if(args[0].equals("true")){
Groups.unit.each(u -> {
if(teams.contains(u.team())) u.team = player.team();
if(teams.contains(u.team())){
u.team = player.team();
u.resetController();
}
});
}

if(args[1].equals("true")){
state.rules.coreDestroyClear = false;
captureTeam = player.team();
Seq<Building> ret = new Seq<>();
data.each(t -> t.buildings.each(b -> {
if(b.block().privileged && !b.block.targetable) return;

b.remove();
b.tile.setNet(b.block(), player.team(), b.rotation());

Expand Down Expand Up @@ -146,8 +155,9 @@ public wheredidtheygo(){
}

public void capture(Seq<Teams.TeamData> data, Player player){ // TODO: This will put heavy load on the cpu and might leak, replace later on
Seq<Building> ret = new Seq<>();
data.each(t -> t.buildings.each(b -> {
if(b.block().privileged && !b.block.targetable) return;

b.remove();
b.tile.setNet(b.block(), player.team(), b.rotation());

Expand All @@ -170,7 +180,11 @@ public void capture(Seq<Teams.TeamData> data, Player player){ // TODO: This will
state.teams.updateTeamStats();

data.each(t -> {
if(t.buildings.size > 0) {
count = 0;
t.buildings.each(b -> {
if(b.block().privileged && !b.block.targetable) ++count;
});
if(t.buildings.size > count){
capture(data, player);
}
});
Expand Down

0 comments on commit d723918

Please sign in to comment.