Also stole the private table setup from the SW gemp, which lets players use the description field with a player's name to set a private table

This commit is contained in:
Christian 'ketura' McCarty
2022-08-24 02:34:31 -05:00
parent c835336e61
commit c04b1a29b2
10 changed files with 80 additions and 23 deletions

View File

@@ -130,11 +130,27 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
String deckName = getFormParameterSafely(postDecoder, "deckName"); String deckName = getFormParameterSafely(postDecoder, "deckName");
String timer = getFormParameterSafely(postDecoder, "timer"); String timer = getFormParameterSafely(postDecoder, "timer");
String desc = getFormParameterSafely(postDecoder, "desc"); String desc = getFormParameterSafely(postDecoder, "desc");
String isPrivateVal = getFormParameterSafely(postDecoder, "isPrivate");
boolean isPrivate = (isPrivateVal != null ? Boolean.valueOf(isPrivateVal) : false);
Player resourceOwner = getResourceOwnerSafely(request, participantId); Player resourceOwner = getResourceOwnerSafely(request, participantId);
if(isPrivate) {
if(desc.length()==0) {
responseWriter.writeXmlResponse(marshalException(new HallException("Private games must have your intended opponent in the description")));
return;
}
if(desc.equalsIgnoreCase(resourceOwner.getName())) {
responseWriter.writeXmlResponse(marshalException(new HallException("Absolutely no playing with yourself!! Private matches must be with someone else.")));
return;
}
}
try { try {
_hallServer.createNewTable(format, resourceOwner, deckName, timer, desc); _hallServer.createNewTable(format, resourceOwner, deckName, timer, desc, isPrivate);
responseWriter.writeXmlResponse(null); responseWriter.writeXmlResponse(null);
} }
catch (HallException e) { catch (HallException e) {
@@ -142,7 +158,7 @@ public class HallRequestHandler extends LotroServerRequestHandler implements Uri
{ {
//try again assuming it's a new player with one of the default library decks selected //try again assuming it's a new player with one of the default library decks selected
Player librarian = _playerDao.getPlayer("Librarian"); Player librarian = _playerDao.getPlayer("Librarian");
_hallServer.spoofNewTable(format, resourceOwner, librarian, deckName, timer, "(New Player) " + desc); _hallServer.spoofNewTable(format, resourceOwner, librarian, deckName, timer, "(New Player) " + desc, isPrivate);
responseWriter.writeXmlResponse(null); responseWriter.writeXmlResponse(null);
} }
catch (HallException ex) { } catch (HallException ex) { }

View File

@@ -387,4 +387,22 @@ a:visited {
display: flex; display: flex;
gap: 4px; gap: 4px;
margin: 1px; margin: 1px;
}
#createTableBut {
min-width: 95px;
}
#supportedFormatsSelect {
min-width: 150px;
}
#decksSelect {
min-width: 220px;
flex-grow:2;
}
#tableDescInput {
min-width: 150px;
flex-grow: 1;
} }

View File

@@ -280,13 +280,13 @@
</div> </div>
</div> </div>
<div id="buttonsDiv" class="flex-horiz"> <div id="buttonsDiv" class="flex-horiz">
<a href="deckBuild.html">Deck builder</a> <a href="deckBuild.html" style="min-width:80px;">Deck builder</a>
| |
<a href='merchant.html' style="text-decoration: line-through underline;">Merchant</a> <a href='merchant.html' style="text-decoration: line-through underline;">Merchant</a>
| |
<select id="supportedFormatsSelect" style='width: 180px'></select> <select id="supportedFormatsSelect" ></select>
<select id="decksSelect" style="width: 220px;flex-grow:1;"></select> <select id="decksSelect" ></select>
<input id='tableDescInput' type='text' maxlength='50' style='width: 150px;' placeHolder='Description (optional)'> <input id='tableDescInput' type='text' maxlength='100' placeHolder='Description (optional, 100 char max)'>
<select id="timerSelect" style="width: 135px;"> <select id="timerSelect" style="width: 135px;">
<option value="default">Default (80m/5m)</option> <option value="default">Default (80m/5m)</option>
<option value="blitz">Blitz! (30m/3m)</option> <option value="blitz">Blitz! (30m/3m)</option>
@@ -294,6 +294,7 @@
<option value="glacial">Glacial (3d/1d)</option> <option value="glacial">Glacial (3d/1d)</option>
</select> </select>
<button id="createTableBut">Create table</button> <button id="createTableBut">Create table</button>
<label style="min-width: fit-content;"><input type='checkbox' id='isPrivateCheckbox'>Private</input></label>
</div> </div>
<div id="chat" class="ui-widget-content grid-container" > <div id="chat" class="ui-widget-content grid-container" >

View File

@@ -640,7 +640,7 @@ var GempLotrCommunication = Class.extend({
dataType:"xml" dataType:"xml"
}); });
}, },
createTable:function (format, deckName, timer, desc, callback, errorMap) { createTable:function (format, deckName, timer, desc, isPrivate, callback, errorMap) {
$.ajax({ $.ajax({
type:"POST", type:"POST",
url:this.url + "/hall", url:this.url + "/hall",
@@ -650,6 +650,7 @@ var GempLotrCommunication = Class.extend({
deckName:deckName, deckName:deckName,
timer:timer, timer:timer,
desc:desc, desc:desc,
isPrivate:isPrivate,
participantId:getUrlParam("participantId")}, participantId:getUrlParam("participantId")},
success:this.deliveryCheck(callback), success:this.deliveryCheck(callback),
error:this.errorCheck(errorMap), error:this.errorCheck(errorMap),

View File

@@ -7,6 +7,7 @@ var GempLotrHallUI = Class.extend({
tableDescInput:null, tableDescInput:null,
timerSelect:null, timerSelect:null,
createTableButton:null, createTableButton:null,
isPrivateCheckbox:null,
tablesDiv:null, tablesDiv:null,
buttonsDiv:null, buttonsDiv:null,
@@ -36,6 +37,7 @@ var GempLotrHallUI = Class.extend({
this.tablesDiv = $("#tablesDiv"); this.tablesDiv = $("#tablesDiv");
this.tableDescInput = $("#tableDescInput"); this.tableDescInput = $("#tableDescInput");
this.isPrivateCheckbox = $("#isPrivateCheckbox");
var hallSettingsStr = $.cookie("hallSettings"); var hallSettingsStr = $.cookie("hallSettings");
if (hallSettingsStr == null) if (hallSettingsStr == null)
@@ -69,9 +71,10 @@ var GempLotrHallUI = Class.extend({
var deck = that.decksSelect.val(); var deck = that.decksSelect.val();
var tableDesc = that.tableDescInput.val(); var tableDesc = that.tableDescInput.val();
var timer = that.timerSelect.val(); var timer = that.timerSelect.val();
var isPrivate = that.isPrivateCheckbox.is(':checked');
if (deck != null) if (deck != null)
console.log("creating table"); console.log("creating table");
that.comm.createTable(format, deck, timer, tableDesc, function (xml) { that.comm.createTable(format, deck, timer, tableDesc, isPrivate, function (xml) {
console.log("received table response"); console.log("received table response");
that.processResponse(xml); that.processResponse(xml);
}); });
@@ -406,6 +409,7 @@ var GempLotrHallUI = Class.extend({
var formatName = table.getAttribute("format"); var formatName = table.getAttribute("format");
var tournamentName = table.getAttribute("tournament"); var tournamentName = table.getAttribute("tournament");
var userDesc = table.getAttribute("userDescription"); var userDesc = table.getAttribute("userDescription");
var isPrivate = (table.getAttribute("isPrivate") === "true");
var players = new Array(); var players = new Array();
if (playersAttr.length > 0) if (playersAttr.length > 0)
players = playersAttr.split(","); players = playersAttr.split(",");
@@ -418,7 +422,14 @@ var GempLotrHallUI = Class.extend({
var name = "<td>" + tournamentName; var name = "<td>" + tournamentName;
if(!!userDesc) if(!!userDesc)
{ {
name += " - <i>[" + userDesc + "]</i>"; if(isPrivate)
{
name += " - <i>Private match for user '" + userDesc + "'.";
}
else
{
name += " - <i>[" + userDesc + "]</i>";
}
} }
name += "</td>"; name += "</td>";
row.append(name); row.append(name);
@@ -445,7 +456,8 @@ var GempLotrHallUI = Class.extend({
}; };
})(id)); })(id));
lastField.append(but); lastField.append(but);
} else { }
else if(!isPrivate || userDesc === chat.userName) {
var that = this; var that = this;
var but = $("<button>Join table</button>"); var but = $("<button>Join table</button>");

View File

@@ -16,10 +16,11 @@ public class GameSettings {
private final int maxSecondsPerPlayer; private final int maxSecondsPerPlayer;
private final int maxSecondsPerDecision; private final int maxSecondsPerDecision;
private final String userDescription; private final String userDescription;
private final boolean isPrivate;
public GameSettings(CollectionType collectionType, LotroFormat lotroFormat, League league, LeagueSerieData leagueSerie, public GameSettings(CollectionType collectionType, LotroFormat lotroFormat, League league, LeagueSerieData leagueSerie,
boolean competitive, boolean privateGame, String timerName, int maxSecondsPerPlayer, int maxSecondsPerDecision, boolean competitive, boolean privateGame, String timerName, int maxSecondsPerPlayer, int maxSecondsPerDecision,
String description) { String description, boolean isPrivate) {
this.collectionType = collectionType; this.collectionType = collectionType;
this.lotroFormat = lotroFormat; this.lotroFormat = lotroFormat;
this.league = league; this.league = league;
@@ -30,6 +31,7 @@ public class GameSettings {
this.maxSecondsPerPlayer = maxSecondsPerPlayer; this.maxSecondsPerPlayer = maxSecondsPerPlayer;
this.maxSecondsPerDecision = maxSecondsPerDecision; this.maxSecondsPerDecision = maxSecondsPerDecision;
this.userDescription = description; this.userDescription = description;
this.isPrivate = isPrivate;
} }
public CollectionType getCollectionType() { public CollectionType getCollectionType() {
@@ -69,4 +71,6 @@ public class GameSettings {
} }
public String getUserDescription() { return userDescription; } public String getUserDescription() { return userDescription; }
public boolean isUserPrivateGame() { return isPrivate; }
} }

View File

@@ -81,7 +81,7 @@ public class HallCommunicationChannel implements LongPollableResource {
} }
@Override @Override
public void visitTable(String tableId, String gameId, boolean watchable, TableStatus status, String statusDescription, String formatName, String tournamentName, String userDesc, List<String> playerIds, boolean playing, String winner) { public void visitTable(String tableId, String gameId, boolean watchable, TableStatus status, String statusDescription, String formatName, String tournamentName, String userDesc, List<String> playerIds, boolean playing, boolean isPrivate, String winner) {
Map<String, String> props = new HashMap<>(); Map<String, String> props = new HashMap<>();
props.put("gameId", gameId); props.put("gameId", gameId);
props.put("watchable", String.valueOf(watchable)); props.put("watchable", String.valueOf(watchable));
@@ -89,6 +89,7 @@ public class HallCommunicationChannel implements LongPollableResource {
props.put("statusDescription", statusDescription); props.put("statusDescription", statusDescription);
props.put("format", formatName); props.put("format", formatName);
props.put("userDescription", userDesc); props.put("userDescription", userDesc);
props.put("isPrivate", String.valueOf(isPrivate));
props.put("tournament", tournamentName); props.put("tournament", tournamentName);
props.put("players", StringUtils.join(playerIds, ",")); props.put("players", StringUtils.join(playerIds, ","));
props.put("playing", String.valueOf(playing)); props.put("playing", String.valueOf(playing));

View File

@@ -11,7 +11,7 @@ public interface HallInfoVisitor {
public void motd(String motd); public void motd(String motd);
public void visitTable(String tableId, String gameId, boolean watchable, TableStatus status, String statusDescription, String formatName, String tournamentName, String userDesc, List<String> playerIds, boolean playing, String winner); public void visitTable(String tableId, String gameId, boolean watchable, TableStatus status, String statusDescription, String formatName, String tournamentName, String userDesc, List<String> playerIds, boolean playing, boolean isPrivate, String winner);
public void visitTournamentQueue(String tournamentQueueKey, int cost, String collectionName, String formatName, String tournamentQueueName, String tournamentPrizes, public void visitTournamentQueue(String tournamentQueueKey, int cost, String collectionName, String formatName, String tournamentQueueName, String tournamentPrizes,
String pairingDescription, String startCondition, int playerCount, boolean playerSignedUp, boolean joinable); String pairingDescription, String startCondition, int playerCount, boolean playerSignedUp, boolean joinable);

View File

@@ -319,11 +319,11 @@ public class HallServer extends AbstractServer {
/** /**
* @return If table created, otherwise <code>false</code> (if the user already is sitting at a table or playing). * @return If table created, otherwise <code>false</code> (if the user already is sitting at a table or playing).
*/ */
public void createNewTable(String type, Player player, String deckName, String timer, String description) throws HallException { public void createNewTable(String type, Player player, String deckName, String timer, String description, boolean isPrivate) throws HallException {
if (_shutdown) if (_shutdown)
throw new HallException("Server is in shutdown mode. Server will be restarted after all running games are finished."); throw new HallException("Server is in shutdown mode. Server will be restarted after all running games are finished.");
GameSettings gameSettings = createGameSettings(type, timer, description); GameSettings gameSettings = createGameSettings(type, timer, description, isPrivate);
LotroDeck lotroDeck = validateUserAndDeck(gameSettings.getLotroFormat(), player, deckName, gameSettings.getCollectionType()); LotroDeck lotroDeck = validateUserAndDeck(gameSettings.getLotroFormat(), player, deckName, gameSettings.getCollectionType());
@@ -339,11 +339,11 @@ public class HallServer extends AbstractServer {
} }
} }
public void spoofNewTable(String type, Player player, Player librarian, String deckName, String timer, String description) throws HallException { public void spoofNewTable(String type, Player player, Player librarian, String deckName, String timer, String description, boolean isPrivate) throws HallException {
if (_shutdown) if (_shutdown)
throw new HallException("Server is in shutdown mode. Server will be restarted after all running games are finished."); throw new HallException("Server is in shutdown mode. Server will be restarted after all running games are finished.");
GameSettings gameSettings = createGameSettings(type, timer, description); GameSettings gameSettings = createGameSettings(type, timer, description, isPrivate);
LotroDeck lotroDeck = validateUserAndDeck(gameSettings.getLotroFormat(), librarian, deckName, gameSettings.getCollectionType()); LotroDeck lotroDeck = validateUserAndDeck(gameSettings.getLotroFormat(), librarian, deckName, gameSettings.getCollectionType());
@@ -359,7 +359,7 @@ public class HallServer extends AbstractServer {
} }
} }
private GameSettings createGameSettings(String type, String timer, String description) throws HallException { private GameSettings createGameSettings(String type, String timer, String description, boolean isPrivate) throws HallException {
League league = null; League league = null;
LeagueSerieData leagueSerie = null; LeagueSerieData leagueSerie = null;
CollectionType collectionType = _defaultCollectionType; CollectionType collectionType = _defaultCollectionType;
@@ -374,6 +374,10 @@ public class HallServer extends AbstractServer {
if (leagueSerie == null) if (leagueSerie == null)
throw new HallException("There is no ongoing serie for that league"); throw new HallException("There is no ongoing serie for that league");
if(isPrivate) {
throw new HallException("League games cannot be private");
}
format = _formatLibrary.getFormat(leagueSerie.getFormat()); format = _formatLibrary.getFormat(leagueSerie.getFormat());
collectionType = leagueSerie.getCollectionType(); collectionType = leagueSerie.getCollectionType();
@@ -385,7 +389,7 @@ public class HallServer extends AbstractServer {
throw new HallException("This format is not supported: " + type); throw new HallException("This format is not supported: " + type);
return new GameSettings(collectionType, format, league, leagueSerie, return new GameSettings(collectionType, format, league, leagueSerie,
league != null, gameTimer.isLongGame(), gameTimer.getName(), gameTimer.getMaxSecondsPerPlayer(), gameTimer.getMaxSecondsPerDecision(), description); league != null, gameTimer.isLongGame(), gameTimer.getName(), gameTimer.getMaxSecondsPerPlayer(), gameTimer.getMaxSecondsPerDecision(), description, isPrivate);
} }
private GameTimer resolveTimer(String timer) { private GameTimer resolveTimer(String timer) {
@@ -812,7 +816,7 @@ public class HallServer extends AbstractServer {
private HallTournamentCallback(Tournament tournament) { private HallTournamentCallback(Tournament tournament) {
_tournament = tournament; _tournament = tournament;
tournamentGameSettings = new GameSettings(null, _formatLibrary.getFormat(_tournament.getFormat()), tournamentGameSettings = new GameSettings(null, _formatLibrary.getFormat(_tournament.getFormat()),
null, null, true, false, "Tournament", 60 * 40, 60 * 5, null); null, null, true, false, "Tournament", 60 * 40, 60 * 5, null, false);
} }
@Override @Override

View File

@@ -177,7 +177,7 @@ public class TableHolder {
players = table.getPlayerNames(); players = table.getPlayerNames();
if (isAdmin || isNoIgnores(players, player.getName())) if (isAdmin || isNoIgnores(players, player.getName()))
visitor.visitTable(tableInformation.getKey(), null, false, HallInfoVisitor.TableStatus.WAITING, "Waiting", table.getGameSettings().getLotroFormat().getName(), getTournamentName(table), table.getGameSettings().getUserDescription(), players, table.getPlayerNames().contains(player.getName()), null); visitor.visitTable(tableInformation.getKey(), null, false, HallInfoVisitor.TableStatus.WAITING, "Waiting", table.getGameSettings().getLotroFormat().getName(), getTournamentName(table), table.getGameSettings().getUserDescription(), players, table.getPlayerNames().contains(player.getName()), table.getGameSettings().isUserPrivateGame(), null);
} }
// Then non-finished // Then non-finished
@@ -192,7 +192,7 @@ public class TableHolder {
if (lotroGameMediator.isFinished()) if (lotroGameMediator.isFinished())
finishedTables.put(runningGame.getKey(), runningTable); finishedTables.put(runningGame.getKey(), runningTable);
else else
visitor.visitTable(runningGame.getKey(), lotroGameMediator.getGameId(), isAdmin || lotroGameMediator.isAllowSpectators(), HallInfoVisitor.TableStatus.PLAYING, lotroGameMediator.getGameStatus(), runningTable.getGameSettings().getLotroFormat().getName(), getTournamentName(runningTable), runningTable.getGameSettings().getUserDescription(), lotroGameMediator.getPlayersPlaying(), lotroGameMediator.getPlayersPlaying().contains(player.getName()), lotroGameMediator.getWinner()); visitor.visitTable(runningGame.getKey(), lotroGameMediator.getGameId(), isAdmin || lotroGameMediator.isAllowSpectators(), HallInfoVisitor.TableStatus.PLAYING, lotroGameMediator.getGameStatus(), runningTable.getGameSettings().getLotroFormat().getName(), getTournamentName(runningTable), runningTable.getGameSettings().getUserDescription(), lotroGameMediator.getPlayersPlaying(), lotroGameMediator.getPlayersPlaying().contains(player.getName()), runningTable.getGameSettings().isUserPrivateGame(), lotroGameMediator.getWinner());
if (!lotroGameMediator.isFinished() && lotroGameMediator.getPlayersPlaying().contains(player.getName())) if (!lotroGameMediator.isFinished() && lotroGameMediator.getPlayersPlaying().contains(player.getName()))
visitor.runningPlayerGame(lotroGameMediator.getGameId()); visitor.runningPlayerGame(lotroGameMediator.getGameId());
@@ -206,7 +206,7 @@ public class TableHolder {
LotroGameMediator lotroGameMediator = runningTable.getLotroGameMediator(); LotroGameMediator lotroGameMediator = runningTable.getLotroGameMediator();
if (lotroGameMediator != null) { if (lotroGameMediator != null) {
if (isAdmin || isNoIgnores(lotroGameMediator.getPlayersPlaying(), player.getName())) if (isAdmin || isNoIgnores(lotroGameMediator.getPlayersPlaying(), player.getName()))
visitor.visitTable(nonPlayingGame.getKey(), lotroGameMediator.getGameId(), false, HallInfoVisitor.TableStatus.FINISHED, lotroGameMediator.getGameStatus(), runningTable.getGameSettings().getLotroFormat().getName(), getTournamentName(runningTable), runningTable.getGameSettings().getUserDescription(), lotroGameMediator.getPlayersPlaying(), lotroGameMediator.getPlayersPlaying().contains(player.getName()), lotroGameMediator.getWinner()); visitor.visitTable(nonPlayingGame.getKey(), lotroGameMediator.getGameId(), false, HallInfoVisitor.TableStatus.FINISHED, lotroGameMediator.getGameStatus(), runningTable.getGameSettings().getLotroFormat().getName(), getTournamentName(runningTable), runningTable.getGameSettings().getUserDescription(), lotroGameMediator.getPlayersPlaying(), lotroGameMediator.getPlayersPlaying().contains(player.getName()), runningTable.getGameSettings().isUserPrivateGame(), lotroGameMediator.getWinner());
} }
} }
} }