mirror of
https://github.com/OpenLiberty/liberty-bikes.git
synced 2025-02-23 11:19:12 +08:00
Update game-service to operate on player IDs instead of just names
This commit is contained in:
parent
ac3d2387b1
commit
abbcefb612
@ -1,6 +1,6 @@
|
||||
<server>
|
||||
<featureManager>
|
||||
<feature>microProfile-1.3</feature>
|
||||
<feature>microProfile-1.2</feature>
|
||||
</featureManager>
|
||||
|
||||
<httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="${httpPort}" httpsPort="${httpsPort}" />
|
||||
|
@ -105,9 +105,7 @@ export class GameComponent implements OnInit {
|
||||
}
|
||||
|
||||
onConnect(evt: MessageEvent) {
|
||||
const name = sessionStorage.getItem('username');
|
||||
const isSpectator = sessionStorage.getItem('isSpectator');
|
||||
if (isSpectator === 'true') {
|
||||
if (sessionStorage.getItem('isSpectator') === 'true') {
|
||||
console.log('is a spectator... showing game id');
|
||||
// Set the Round ID and make visible
|
||||
$('#game-code').html(this.roundId);
|
||||
@ -116,7 +114,7 @@ export class GameComponent implements OnInit {
|
||||
gameId.addClass('d-inline-block');
|
||||
this.gameSocket.sendText(JSON.stringify({'spectatorjoined': true}));
|
||||
} else {
|
||||
this.gameSocket.sendText(JSON.stringify({'playerjoined': name}));
|
||||
this.gameSocket.sendText(JSON.stringify({'playerjoined': sessionStorage.getItem('userId')}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,11 +28,17 @@ export class LoginComponent implements OnInit {
|
||||
let ngZone = this.ngZone;
|
||||
let router = this.router;
|
||||
let roundID: string = $('#roundid').val();
|
||||
let username: string = $('#username').val();
|
||||
roundID = roundID.toUpperCase().replace(/[^A-Z]/g, '');
|
||||
// TODO: Validate form input in a more elegant way than alert()
|
||||
if (roundID.length !== 4) {
|
||||
alert(roundID + ' is not a valid round ID, because it must be 4 letters long');
|
||||
return;
|
||||
}
|
||||
if (username.length < 1) {
|
||||
alert('Username must not be empty');
|
||||
return;
|
||||
}
|
||||
|
||||
$.get(`http://${document.location.hostname}:8080/round/${roundID}`, function(data) {
|
||||
if (data === undefined) {
|
||||
@ -51,18 +57,27 @@ export class LoginComponent implements OnInit {
|
||||
alert('Game round has already finished!');
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.setItem('username', $('#username').val());
|
||||
sessionStorage.setItem('roundId', roundID);
|
||||
if (gameBoard === true) {
|
||||
ngZone.run(() => {
|
||||
router.navigate(['/game']);
|
||||
});
|
||||
} else {
|
||||
ngZone.run(() => {
|
||||
router.navigate(['/play']);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Register the player here until we get a proper 'login' flow
|
||||
$.post(`http://${document.location.hostname}:8081/player/create?name=${username}`, function(response) {
|
||||
console.log(`Created a new player with ID=${response}`);
|
||||
sessionStorage.setItem('userId', response);
|
||||
|
||||
|
||||
// TEMP: to prevent a race condition, putting this code inside of the player create callback to ensure that
|
||||
// userId is set in the session storage before proceeding to the game board
|
||||
sessionStorage.setItem('username', username);
|
||||
sessionStorage.setItem('roundId', roundID);
|
||||
if (gameBoard === true) {
|
||||
ngZone.run(() => {
|
||||
router.navigate(['/game']);
|
||||
});
|
||||
} else {
|
||||
ngZone.run(() => {
|
||||
router.navigate(['/play']);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ liberty {
|
||||
name = 'game-service'
|
||||
dropins = [war]
|
||||
bootstrapProperties = ['httpPort': httpPort, 'httpsPort': httpsPort]
|
||||
jvmOptions = ['-Dorg.libertybikes.restclient.PlayerService/mp-rest/url=http://localhost:8081/']
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.websocket.Session;
|
||||
|
||||
import org.libertybikes.game.core.ClientMessage.GameEvent;
|
||||
import org.libertybikes.game.core.Player.STATUS;
|
||||
import org.libertybikes.game.round.service.GameRoundService;
|
||||
import org.libertybikes.game.round.service.GameRoundWebsocket;
|
||||
@ -49,7 +48,7 @@ public class GameRound implements Runnable {
|
||||
private final AtomicBoolean gameRunning = new AtomicBoolean(false);
|
||||
private final AtomicBoolean paused = new AtomicBoolean(false);
|
||||
private final Map<Session, Client> clients = new HashMap<>();
|
||||
private final boolean[] takenPlayerSlots = new boolean[PlayerFactory.MAX_PLAYERS];
|
||||
private final boolean[] takenPlayerSlots = new boolean[Player.MAX_PLAYERS];
|
||||
|
||||
private int ticksFromGameEnd = 0;
|
||||
|
||||
@ -77,26 +76,13 @@ public class GameRound implements Runnable {
|
||||
return board;
|
||||
}
|
||||
|
||||
public void handleMessage(ClientMessage msg, Session session) {
|
||||
if (GameEvent.GAME_START == msg.event)
|
||||
startGame();
|
||||
|
||||
if (msg.direction != null) {
|
||||
Client c = clients.get(session);
|
||||
if (c.isPlayer())
|
||||
c.player.setDirection(msg.direction);
|
||||
}
|
||||
|
||||
if (msg.playerJoinedId != null) {
|
||||
addPlayer(session, msg.playerJoinedId);
|
||||
}
|
||||
|
||||
if (Boolean.TRUE == msg.isSpectator) {
|
||||
addSpectator(session);
|
||||
}
|
||||
public void updatePlayerDirection(Session playerSession, ClientMessage msg) {
|
||||
Client c = clients.get(playerSession);
|
||||
if (c.isPlayer())
|
||||
c.player.setDirection(msg.direction);
|
||||
}
|
||||
|
||||
public void addPlayer(Session s, String playerId) {
|
||||
public void addPlayer(Session s, String playerId, String playerName) {
|
||||
// Front end should be preventing a player joining a full game but
|
||||
// defensive programming
|
||||
if (gameState != State.OPEN) {
|
||||
@ -104,7 +90,7 @@ public class GameRound implements Runnable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (board.players.size() + 1 > PlayerFactory.MAX_PLAYERS - 1) {
|
||||
if (board.players.size() + 1 > Player.MAX_PLAYERS - 1) {
|
||||
gameState = State.FULL;
|
||||
}
|
||||
|
||||
@ -120,7 +106,7 @@ public class GameRound implements Runnable {
|
||||
}
|
||||
|
||||
// Initialize Player
|
||||
Player p = PlayerFactory.initNextPlayer(this, playerId, playerNum);
|
||||
Player p = new Player(playerId, playerName, playerNum);
|
||||
board.addPlayer(p);
|
||||
clients.put(s, new Client(s, p));
|
||||
System.out.println("Player " + playerId + " has joined.");
|
||||
@ -137,11 +123,11 @@ public class GameRound implements Runnable {
|
||||
|
||||
private void removePlayer(Player p) {
|
||||
p.disconnect();
|
||||
System.out.println(p.playerName + " disconnected.");
|
||||
System.out.println(p.name + " disconnected.");
|
||||
broadcastPlayerList();
|
||||
|
||||
// Open player slot for new joiners
|
||||
if (State.FULL == gameState && board.players.size() - 1 < PlayerFactory.MAX_PLAYERS) {
|
||||
if (State.FULL == gameState && board.players.size() - 1 < Player.MAX_PLAYERS) {
|
||||
gameState = State.OPEN;
|
||||
}
|
||||
takenPlayerSlots[p.getPlayerNum()] = false;
|
||||
@ -230,7 +216,7 @@ public class GameRound implements Runnable {
|
||||
JsonArrayBuilder array = Json.createArrayBuilder();
|
||||
for (Player p : players()) {
|
||||
array.add(Json.createObjectBuilder()
|
||||
.add("name", p.playerName)
|
||||
.add("name", p.name)
|
||||
.add("status", p.getStatus().toString())
|
||||
.add("color", p.color));
|
||||
}
|
||||
|
@ -3,6 +3,10 @@
|
||||
*/
|
||||
package org.libertybikes.game.core;
|
||||
|
||||
import javax.json.bind.annotation.JsonbPropertyOrder;
|
||||
import javax.json.bind.annotation.JsonbTransient;
|
||||
|
||||
@JsonbPropertyOrder({ "id", "name", "color", "status", "x", "y", "isAlive" })
|
||||
public class Player {
|
||||
|
||||
public static enum STATUS {
|
||||
@ -13,29 +17,58 @@ public class Player {
|
||||
Disconnected
|
||||
}
|
||||
|
||||
private static enum PlayerStartingData {
|
||||
START_1("#DF740C", 10, 10, DIRECTION.RIGHT),
|
||||
START_2("#FF0000", 10, GameBoard.BOARD_SIZE - 10, DIRECTION.UP),
|
||||
START_3("#6FC3DF", GameBoard.BOARD_SIZE - 10, 10, DIRECTION.DOWN),
|
||||
START_4("#FFE64D", GameBoard.BOARD_SIZE - 10, GameBoard.BOARD_SIZE - 10, DIRECTION.LEFT);
|
||||
|
||||
public final String color;
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final DIRECTION dir;
|
||||
|
||||
PlayerStartingData(String color, int x, int y, DIRECTION dir) {
|
||||
this.color = color;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int MAX_PLAYERS = PlayerStartingData.values().length;
|
||||
private static final PlayerStartingData[] startingData = new PlayerStartingData[] { PlayerStartingData.START_1, PlayerStartingData.START_2,
|
||||
PlayerStartingData.START_3, PlayerStartingData.START_4 };
|
||||
|
||||
// Properties exposed by JSON-B
|
||||
public final String name;
|
||||
public final String id;
|
||||
public final String color;
|
||||
public DIRECTION direction = DIRECTION.RIGHT;
|
||||
private DIRECTION lastDirection = null;
|
||||
private DIRECTION desiredNextDirection = null;
|
||||
public int x;
|
||||
public int y;
|
||||
public int playerNum;
|
||||
public String playerName;
|
||||
public boolean isAlive = true;
|
||||
private STATUS playerStatus = STATUS.Connected;
|
||||
|
||||
public Player(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
private final int playerNum;
|
||||
private DIRECTION direction;
|
||||
private DIRECTION lastDirection = null;
|
||||
private DIRECTION desiredNextDirection = null;
|
||||
|
||||
public Player(String color, int xstart, int ystart, int playerNum) {
|
||||
this.color = color;
|
||||
x = xstart;
|
||||
y = ystart;
|
||||
public Player(String id, String name, int playerNum) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.playerNum = playerNum;
|
||||
|
||||
// Initialize starting data
|
||||
PlayerStartingData data = startingData[playerNum];
|
||||
color = data.color;
|
||||
direction = data.dir;
|
||||
x = data.x;
|
||||
y = data.y;
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
// TODO: Use JSON-B to eliminate the need for this method
|
||||
// {"color":"#FF0000","coords":{"x":251,"y":89}}
|
||||
StringBuffer sb = new StringBuffer("{\"color\":\"");
|
||||
sb.append(this.color);
|
||||
@ -65,10 +98,6 @@ public class Player {
|
||||
direction = newDirection;
|
||||
}
|
||||
|
||||
public DIRECTION getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a player forward one space in whatever direction they are facing currently.
|
||||
*
|
||||
@ -128,6 +157,7 @@ public class Player {
|
||||
return this.playerStatus;
|
||||
}
|
||||
|
||||
@JsonbTransient
|
||||
public int getPlayerNum() {
|
||||
return this.playerNum;
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.libertybikes.game.core;
|
||||
|
||||
public class PlayerFactory {
|
||||
|
||||
public static int MAX_PLAYERS = PlayerData.values().length;
|
||||
|
||||
private static enum PlayerData {
|
||||
START_1("#DF740C", 10, 10, DIRECTION.RIGHT),
|
||||
START_2("#FF0000", 10, GameBoard.BOARD_SIZE - 10, DIRECTION.UP),
|
||||
START_3("#6FC3DF", GameBoard.BOARD_SIZE - 10, 10, DIRECTION.DOWN),
|
||||
START_4("#FFE64D", GameBoard.BOARD_SIZE - 10, GameBoard.BOARD_SIZE - 10, DIRECTION.LEFT);
|
||||
|
||||
public final String color;
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final DIRECTION dir;
|
||||
|
||||
PlayerData(String color, int x, int y, DIRECTION dir) {
|
||||
this.color = color;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
private static final PlayerData[] startingData = new PlayerData[] { PlayerData.START_1, PlayerData.START_2, PlayerData.START_3, PlayerData.START_4 };
|
||||
|
||||
public static Player initNextPlayer(GameRound g, String name, int playerNum) {
|
||||
PlayerData data = startingData[playerNum];
|
||||
Player p = new Player(data.color, data.x, data.y, playerNum);
|
||||
p.direction = data.dir;
|
||||
p.playerName = name;
|
||||
return p;
|
||||
}
|
||||
}
|
@ -18,9 +18,11 @@ import javax.websocket.Session;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.libertybikes.game.core.ClientMessage;
|
||||
import org.libertybikes.game.core.ClientMessage.GameEvent;
|
||||
import org.libertybikes.game.core.GameRound;
|
||||
import org.libertybikes.restclient.PlayerService;
|
||||
|
||||
@Dependent
|
||||
@ServerEndpoint("/round/ws/{roundId}")
|
||||
@ -29,6 +31,10 @@ public class GameRoundWebsocket {
|
||||
@Inject
|
||||
GameRoundService gameSvc;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
PlayerService playerSvc;
|
||||
|
||||
private final Jsonb jsonb = JsonbBuilder.create();
|
||||
|
||||
@OnOpen
|
||||
@ -59,7 +65,17 @@ public class GameRoundWebsocket {
|
||||
if (msg.event != null && GameEvent.GAME_REQUEUE == msg.event) {
|
||||
requeueClient(gameSvc, round, session);
|
||||
} else {
|
||||
round.handleMessage(msg, session);
|
||||
if (GameEvent.GAME_START == msg.event)
|
||||
round.startGame();
|
||||
if (msg.direction != null)
|
||||
round.updatePlayerDirection(session, msg);
|
||||
if (msg.playerJoinedId != null) {
|
||||
org.libertybikes.restclient.Player playerResponse = playerSvc.getPlayerById(msg.playerJoinedId);
|
||||
round.addPlayer(session, msg.playerJoinedId, playerResponse.name);
|
||||
}
|
||||
if (Boolean.TRUE == msg.isSpectator) {
|
||||
round.addSpectator(session);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@ -0,0 +1,9 @@
|
||||
package org.libertybikes.restclient;
|
||||
|
||||
public class Player {
|
||||
|
||||
public String id;
|
||||
|
||||
public String name;
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.libertybikes.restclient;
|
||||
|
||||
import javax.enterprise.context.Dependent;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
@Dependent
|
||||
@RegisterRestClient
|
||||
@Path("/player")
|
||||
public interface PlayerService {
|
||||
|
||||
@GET
|
||||
@Path("/{playerId}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Player getPlayerById(@PathParam("playerId") String id);
|
||||
|
||||
@POST
|
||||
@Path("/{playerId}/win")
|
||||
public Response addWin(@PathParam("playerId") String id);
|
||||
|
||||
@POST
|
||||
@Path("/{playerId}/loss")
|
||||
public Response addLoss(@PathParam("playerId") String id);
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
<server>
|
||||
<featureManager>
|
||||
<feature>microProfile-1.3</feature>
|
||||
<feature>microProfile-1.2</feature>
|
||||
<feature>mpRestClient-1.0</feature>
|
||||
<feature>websocket-1.1</feature>
|
||||
<feature>jaxrs-2.1</feature>
|
||||
<feature>jsonb-1.0</feature>
|
||||
|
@ -58,15 +58,19 @@ public class JsonDataTest {
|
||||
GameBoard board = new GameBoard();
|
||||
assertEquals("{\"movingObstacles\":[],\"obstacles\":[],\"players\":[]}", jsonb.toJson(board));
|
||||
|
||||
String obstacleJson = "{\"height\":2,\"width\":1,\"x\":3,\"y\":4}";
|
||||
board.addObstacle(new Obstacle(1, 2, 3, 4));
|
||||
assertEquals("{\"movingObstacles\":[],\"obstacles\":[{\"height\":2,\"width\":1,\"x\":3,\"y\":4}],\"players\":[]}", jsonb.toJson(board));
|
||||
assertEquals("{\"movingObstacles\":[],\"obstacles\":[" + obstacleJson + "],\"players\":[]}", jsonb.toJson(board));
|
||||
|
||||
board.addPlayer(new Player("#1234", 10, 11, 0));
|
||||
assertEquals("{\"movingObstacles\":[],\"obstacles\":[{\"height\":2,\"width\":1,\"x\":3,\"y\":4}],\"players\":[{\"color\":\"#1234\",\"direction\":\"RIGHT\",\"isAlive\":true,\"playerNum\":0,\"status\":\"Connected\",\"x\":10,\"y\":11}]}",
|
||||
// @JsonbPropertyOrder({ "id", "name", "color", "x", "y", "isAlive" })
|
||||
String bobJson = "{\"id\":\"1234\",\"name\":\"Bob\",\"color\":\"#DF740C\",\"status\":\"Connected\",\"x\":10,\"y\":10,\"isAlive\":true}";
|
||||
board.addPlayer(new Player("1234", "Bob", 0));
|
||||
assertEquals("{\"movingObstacles\":[],\"obstacles\":[" + obstacleJson + "],\"players\":[" + bobJson + "]}",
|
||||
jsonb.toJson(board));
|
||||
|
||||
board.addObstacle(new MovingObstacle(11,12,13,14,-1,2,50));
|
||||
assertEquals("{\"movingObstacles\":[{\"height\":12,\"width\":11,\"x\":13,\"y\":14,\"currentDelay\":0,\"hasMoved\":false,\"moveDelay\":50,\"oldX\":0,\"oldY\":0,\"xDir\":-1,\"yDir\":2}],\"obstacles\":[{\"height\":2,\"width\":1,\"x\":3,\"y\":4}],\"players\":[{\"color\":\"#1234\",\"direction\":\"RIGHT\",\"isAlive\":true,\"playerNum\":0,\"status\":\"Connected\",\"x\":10,\"y\":11}]}",
|
||||
|
||||
board.addObstacle(new MovingObstacle(11, 12, 13, 14, -1, 2, 50));
|
||||
assertEquals("{\"movingObstacles\":[{\"height\":12,\"width\":11,\"x\":13,\"y\":14,\"currentDelay\":0,\"hasMoved\":false,\"moveDelay\":50,\"oldX\":0,\"oldY\":0,\"xDir\":-1,\"yDir\":2}],\"obstacles\":["
|
||||
+ obstacleJson + "],\"players\":[" + bobJson + "]}",
|
||||
jsonb.toJson(board));
|
||||
}
|
||||
|
||||
@ -78,6 +82,14 @@ public class JsonDataTest {
|
||||
assertContains("nextRoundId\":\"", jsonb.toJson(round));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindPlayer() {
|
||||
String playerSvcResponse = "{\"id\":\"112233\",\"name\":\"andy\",\"stats\":{\"totalGames\":0,\"numWins\":0}}";
|
||||
org.libertybikes.restclient.Player p = jsonb.fromJson(playerSvcResponse, org.libertybikes.restclient.Player.class);
|
||||
assertEquals("112233", p.id);
|
||||
assertEquals("andy", p.name);
|
||||
}
|
||||
|
||||
private void assertContains(String expected, String search) {
|
||||
assertTrue("Did not find '" + expected + "' inside of the string: " + search, search.contains(expected));
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ public class PlayerService {
|
||||
return db.getAll();
|
||||
}
|
||||
|
||||
@GET
|
||||
@POST
|
||||
@Path("/create")
|
||||
public String createPlayer(@QueryParam("name") String name) {
|
||||
@ -61,7 +60,7 @@ public class PlayerService {
|
||||
return db.get(id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@POST
|
||||
@Path("/{playerId}/win")
|
||||
public Response addWin(@PathParam("playerId") String id) {
|
||||
Player p = getPlayerById(id);
|
||||
@ -74,7 +73,7 @@ public class PlayerService {
|
||||
return Response.ok(wins).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@POST
|
||||
@Path("/{playerId}/loss")
|
||||
public Response addLoss(@PathParam("playerId") String id) {
|
||||
Player p = getPlayerById(id);
|
||||
|
@ -1,6 +1,6 @@
|
||||
<server>
|
||||
<featureManager>
|
||||
<feature>microProfile-1.3</feature>
|
||||
<feature>microProfile-1.2</feature>
|
||||
</featureManager>
|
||||
|
||||
<httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="${httpPort}" httpsPort="${httpsPort}" />
|
||||
|
15
player-service/src/main/webapp/WEB-INF/ibm-web-ext.xml
Normal file
15
player-service/src/main/webapp/WEB-INF/ibm-web-ext.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-ext
|
||||
xmlns="http://websphere.ibm.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_1.xsd"
|
||||
version="1.1">
|
||||
|
||||
<reload-interval value="3"/>
|
||||
<context-root uri="/" />
|
||||
<enable-directory-browsing value="false"/>
|
||||
<enable-file-serving value="true"/>
|
||||
<enable-reloading value="true"/>
|
||||
<enable-serving-servlets-by-class-name value="false" />
|
||||
|
||||
</web-ext>
|
Loading…
Reference in New Issue
Block a user