/*
* Copyright (C) 2012 maartenl
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package mmud.rest.services;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import mmud.Constants;
import mmud.Utils;
import mmud.commands.CommandFactory;
import mmud.commands.CommandFactory.UserCommandInfo;
import mmud.commands.CommandRunner;
import mmud.database.entities.characters.Person;
import mmud.database.entities.characters.User;
import mmud.database.entities.game.Board;
import mmud.database.entities.game.BoardMessage;
import mmud.database.entities.game.DisplayInterface;
import mmud.database.entities.game.Macro;
import mmud.database.entities.game.MacroPK;
import mmud.database.entities.game.Room;
import mmud.database.entities.game.UserCommand;
import mmud.database.entities.game.Worldattribute;
import mmud.database.enums.Sex;
import mmud.exceptions.MudException;
import mmud.exceptions.MudWebException;
import mmud.rest.webentities.PrivateDisplay;
import mmud.rest.webentities.PrivateLog;
import mmud.rest.webentities.PrivatePerson;
import mmud.scripting.RoomsInterface;
import mmud.scripting.WorldInterface;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;
/**
* Takes care of all the game-related functions.
* <img
* src="doc-files/Gamebean.png">
*
* @startuml doc-files/Gamebean.png
* (*) --> "Create character"
* --> "Login"
* --> "Play"
* --> "Retrieve log"
* --> "Play"
* --> "Quit"
* -->(*)
* @enduml
* @author maartenl
*/
@DeclareRoles("player")
@RolesAllowed("player")
@Stateless
@LocalBean
@Path("/game")
public class GameBean implements RoomsInterface, WorldInterface
{
@EJB
private BoardBean boardBean;
@EJB
private PersonBean personBean;
@EJB
private MailBean mailBean;
@EJB
private CommandRunner commandRunner;
@EJB
private LogBean logBean;
@PersistenceContext(unitName = "karchangamePU")
private EntityManager em;
@Resource
private SessionContext context;
/**
* The ip address of the karchan server (vps386.directvps.nl).
* This address means that the call
* to the game came from the server itself, and therefore we require
* access to the {@link #X_FORWARDED_FOR} header.
*/
public static final String VPS386 = "194.145.201.161";
/**
* If the call was forwarded from an Internet
* proxy, then the original ip is stored in this http header.
*/
public static final String X_FORWARDED_FOR = "X-Forwarded-For";
/**
* Returns the entity manager of JPA. This is defined in
* build/web/WEB-INF/classes/META-INF/persistence.xml.
*
* @return EntityManager
*/
protected EntityManager getEntityManager()
{
return em;
}
private static final Logger itsLog = Logger.getLogger(GameBean.class.getName());
/**
* <p>
* This method should be called to verify that the target of a certain
* action is indeed a proper authenticated user.</p>
* <p>
* <img
* src="doc-files/Gamebean_authenticate.png"></p>
*
* @param name the name to identify the person
* @throws WebApplicationException NOT_FOUND, if the user is either not
* found or is not a proper user. BAD_REQUEST if an unexpected exception
* crops up or provided info is really not proper. UNAUTHORIZED if session
* passwords do not match.
* @startuml doc-files/Gamebean_authenticate.png
* (*) --> "find character"
* --> "character found"
* --> "character == user"
* --> "session password is good"
* -->(*)
* @enduml
*/
private User authenticate(String name)
{
if (!getPlayerName().equals(name))
{
throw new MudWebException(name, "You are not logged in as " + name, Response.Status.UNAUTHORIZED);
}
User person = getPlayer(name);
if (!person.isActive())
{
throw new MudWebException(name, name + " is not playing the game. Please log in.", Response.Status.UNAUTHORIZED);
}
return person;
}
private User authenticateToEnterGame(String name)
{
if (!getPlayerName().equals(name))
{
throw new MudWebException(name, "You are not logged in as " + name, Response.Status.UNAUTHORIZED);
}
User person = getPlayer(name);
return person;
}
/**
* <p>
* This method should be called to verify that the target of a certain
* action is a user with the appropriate password.</p>
* <p>
* <img
* src="doc-files/Gamebean_authenticateWithPassword.png"></p>
*
* @param name the name to identify the person
* @return the authenticated User
* @throws WebApplicationException BAD_REQUEST if an unexpected exception
* crops up or provided info is really not proper. UNAUTHORIZED if session
* passwords do not match or user not found.
* @startuml doc-files/Gamebean_authenticateWithPassword.png
* (*) --> "find character"
* --> "character found"
* --> "character == user"
* --> "password is good"
* -->(*)
* @enduml
*/
protected User getPlayer(String name)
{
if (Utils.isOffline())
{
throw new MudWebException(name, "Game is offline", Response.Status.NO_CONTENT);
}
User person = getEntityManager().find(User.class, name);
if (person == null)
{
throw new MudWebException(name,
name + " was not found.",
"User was not found (" + name + ")",
Response.Status.NOT_FOUND);
}
if (!person.isUser())
{
throw new MudWebException(name,
name + " is not a user.",
"User was not a user (" + name + ")",
Response.Status.BAD_REQUEST);
}
if (person.getTimeout() > 0)
{
throw new MudWebException(name, name + " has been kicked out of the game and "
+ "is not allowed to logon for " + person.getTimeout() + " minutes.",
Response.Status.FORBIDDEN);
}
return person;
}
/**
* <p>
* Checks to see if a person is banned from playing.</p>
* <p>
* <img
* src="doc-files/Gamebean_isBanned.png"></p>
*
* @param name the name of the person
* @param address the ip address the person is playing from
* @return true if banned, false otherwise.
* @startuml doc-files/Gamebean_isBanned.png
* (*) --> "check silly names"
* --> "check unbanned"
* --> "check address banned"
* --> "check name banned"
* -->(*)
* @enduml
*/
public boolean isBanned(String name, String address)
{
// check silly names
Query query = getEntityManager().createNamedQuery("SillyName.findByName");
query.setParameter("name", name);
query.setMaxResults(1);
if (!query.getResultList().isEmpty())
{
// silly name found!
return true;
}
// check unbanned names
query = getEntityManager().createNamedQuery("UnbanTable.findByName");
query.setParameter("name", name);
query.setMaxResults(1);
if (!query.getResultList().isEmpty())
{
// unbanned name found!
return false;
}
// check address banned
String address2 = "bogushostman!";
try
{
InetAddress inetAddress = InetAddress.getByName(address2);
address2 = inetAddress.getHostName();
} catch (UnknownHostException e)
{
// ignore this.
}
query = getEntityManager().createNamedQuery("BanTable.find");
query.setParameter("address", address);
query.setParameter("address2", address2);
query.setMaxResults(1);
if (!query.getResultList().isEmpty())
{
// banned address found!
return true;
}
// check name banned
query = getEntityManager().createNamedQuery("BannedName.find");
query.setParameter("name", name);
query.setMaxResults(1);
if (!query.getResultList().isEmpty())
{
// banned name found!
return true;
}
return false;
}
/**
* <p>
* Creates a new character, suitable for playing.</p>
* <p>
* <img
* src="doc-files/Gamebean_create.png"></p>
* @param requestContext for headers, like remote address.
* @param name the name of the user
* @param pperson the data of the new character
* @return NO_CONTENT if the game is offline for maintenance.
* @throws WebApplicationException BAD_REQUEST if an unexpected exception
* crops up or something could not be validated.
* @startuml doc-files/Gamebean_create.png
* (*) --> "check for offline"
* --> "check presence of data"
* --> "check name == pperson.name"
* --> "check password == password2"
* --> "check isBanned"
* --> "check already person"
* --> "create person"
* -->(*)
* @enduml
*/
@PermitAll
@POST
@Path("{name}")
@Produces(
{
MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON
})
public Response create(@Context HttpServletRequest requestContext, @PathParam("name") String name, PrivatePerson pperson)
{
itsLog.finer("entering create");
String address = requestContext.getRemoteAddr();
try
{
if (Utils.isOffline())
{
throw new MudWebException(name, "Game is offline", Response.Status.NO_CONTENT);
}
if (pperson == null)
{
throw new MudWebException(name, "No data received.", Response.Status.BAD_REQUEST);
}
if (name == null || !pperson.name.equals(name))
{
throw new MudWebException(name, "Wrong data received.", Response.Status.BAD_REQUEST);
}
if (pperson.password == null || !pperson.password.equals(pperson.password2))
{
throw new MudWebException(name,
"Passwords do not match.",
"Passwords do not match.",
Response.Status.BAD_REQUEST);
}
User person = new User();
person.setName(name);
person.setPassword(pperson.password);
person.setNewpassword(pperson.password);
if (isBanned(name, address))
{
// is banned
throw new MudWebException(name,
name + " was banned.",
"User was banned (" + name + ", " + address + ")",
Response.Status.FORBIDDEN);
}
Person foundPerson = getEntityManager().find(Person.class, name);
if (foundPerson != null)
{
// already a person
throw new MudWebException(name,
name + " already exists.",
"User already exists (" + name + ", " + address + ")",
Response.Status.FOUND);
}
// everything's cool! Let's do this!
person.setActive(false);
person.setTitle(pperson.title);
person.setRealname(pperson.realname);
person.setEmail(pperson.email);
person.setAddress(address);
person.setSex(Sex.createFromString(pperson.sex));
person.setRace(pperson.race);
person.setAge(pperson.age);
person.setHeight(pperson.height);
person.setWidth(pperson.width);
person.setComplexion(pperson.complexion);
person.setEyes(pperson.eyes);
person.setFace(pperson.face);
person.setHair(pperson.hair);
person.setBeard(pperson.beard);
person.setArm(pperson.arm);
person.setLeg(pperson.leg);
person.setBirth(new Date());
person.setCreation(new Date());
person.setRoom(getEntityManager().find(Room.class, Room.STARTERS_ROOM));
getEntityManager().persist(person);
// TODO automatically add a welcome mail.
logBean.writeLog(person, "character created.");
} catch (MudWebException e)
{
//ignore
throw e;
} catch (ConstraintViolationException e)
{
StringBuilder buffer = new StringBuilder("ConstraintViolationException:");
for (ConstraintViolation<?> violation : e.getConstraintViolations())
{
buffer.append(violation);
}
throw new MudWebException(name, buffer.toString(), e, Response.Status.BAD_REQUEST);
} catch (javax.persistence.PersistenceException f)
{
if (f.getCause().getClass().getName().equals("ConstraintViolationException"))
{
ConstraintViolationException e = (ConstraintViolationException) f.getCause();
StringBuilder buffer = new StringBuilder("PersistenceException:");
for (ConstraintViolation<?> violation : e.getConstraintViolations())
{
buffer.append(violation);
}
throw new MudWebException(name, buffer.toString(), f, Response.Status.BAD_REQUEST);
}
throw f;
} catch (MudException e)
{
throw new MudWebException(name, e, Response.Status.BAD_REQUEST);
}
return Response.ok().build();
}
/**
* Deletes a character, permanently. Use with extreme caution.
*
* @param name the name of the user
* @return Response.ok
* @throws WebApplicationException BAD_REQUEST if an unexpected exception
* crops up.
*/
@DELETE
@Path("{name}")
@Produces(
{
MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON
})
public Response delete(@PathParam("name") String name)
{
itsLog.finer("entering delete");
Person person = authenticate(name);
try
{
getEntityManager().remove(person);
logBean.writeLog(person, "character deleted.");
} catch (WebApplicationException e)
{
//ignore
throw e;
} catch (Exception e)
{
throw new MudWebException(name, e, Response.Status.BAD_REQUEST);
}
return Response.ok().build();
}
/**
* Logs a player into the server. Once logged in, he/she can start playing
* the game. Url is for example http://localhost:8080/karchangame/resources/game/Karn/logon?password=itsasecret..
*
* @param requestContext the context of the request, useful for example querying
* for the IP address.
* @param password password for verification of the user.
* @param name the name of the user
*/
@PermitAll
@PUT
@Path("{name}/logon")
public void logon(@Context HttpServletRequest requestContext, @PathParam("name") String name, @QueryParam("password") String password)
{
itsLog.finer("entering logon");
String address = requestContext.getHeader(X_FORWARDED_FOR);
if ((address == null) || ("".equals(address.trim())))
{
address = requestContext.getRemoteAddr();
if (VPS386.equals(address))
{
throw new MudWebException(name,
"User has server address.",
"User has server address (" + name + ", " + address + ")",
Response.Status.BAD_REQUEST);
}
}
if ((address == null) || ("".equals(address.trim())))
{
throw new MudWebException(name,
"User has no address.",
"User has no address (" + name + ", " + address + ")",
Response.Status.BAD_REQUEST);
}
if (Utils.isOffline())
{
throw new MudWebException(name, "Game is offline", Response.Status.NO_CONTENT);
}
if (isBanned(name, address))
{
throw new MudWebException(name, "User was banned",
"User was banned (" + name + ", " + address + ")",
Response.Status.FORBIDDEN);
}
User person = getPlayer(name);
// nasty work-around for Catalina AuthenticatorBase to be able to
// change/create the session cookie
requestContext.getSession();
try
{
requestContext.login(name, password);
} catch (ServletException ex)
{
if (ex.getCause() != null)
{
Logger.getLogger(GameBean.class.getName()).log(Level.SEVERE, null, ex.getCause());
}
if (ex.getMessage().equals("Login failed"))
{
throw new WebApplicationException(ex, Response.Status.UNAUTHORIZED);
}
if (ex.getMessage().equals("This is request has already been authenticated"))
{
return;
}
Logger.getLogger(GameBean.class.getName()).log(Level.SEVERE, null, ex);
throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR);
}
person.setAddress(address);
person.setNewpassword(password);
}
/**
* Logs a player off.
*
* @param requestContext the context of the request, useful for example querying
* for the IP address.
*/
@PUT
@Path("{name}/logoff")
public void logoff(@Context HttpServletRequest requestContext)
{
itsLog.finer("entering logoff");
// nasty work-around for Catalina AuthenticatorBase to be able to
// change/create the session cookie
requestContext.getSession();
try
{
requestContext.logout();
} catch (ServletException ex)
{
if (ex.getCause() != null)
{
Logger.getLogger(GameBean.class.getName()).log(Level.SEVERE, null, ex.getCause());
}
if (ex.getMessage().equals("Logout failed"))
{
throw new WebApplicationException(ex, Response.Status.UNAUTHORIZED);
}
Logger.getLogger(GameBean.class.getName()).log(Level.SEVERE, null, ex);
throw new WebApplicationException(ex, Response.Status.INTERNAL_SERVER_ERROR);
}
}
/**
* Starts playing the game.
*
* @param requestContext used for retrieving the ip address/hostname of the
* player for determining ban-rules and the like.
* @param name the name of the character/player
* @throws WebApplicationException <ul><li>BAD_REQUEST if an unexpected exception
* crops up.</li>
* <li>NO_CONTENT if the game is offline</li>
* <li>FORBIDDEN, if the player is banned.</li>
* </ul>
*/
@POST
@Path("{name}/enter")
@Produces(
{
MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON
})
public void enterGame(@Context HttpServletRequest requestContext, @PathParam("name") String name)
{
itsLog.finer("entering enterGame");
User person = authenticateToEnterGame(name);
try
{
person.activate();
// write logon message
Board newsBoard = boardBean.getNewsBoard();
StringBuilder buffer = new StringBuilder(newsBoard.getDescription());
List<BoardMessage> news = boardBean.getNews();
for (BoardMessage newMessage : news)
{
buffer.append("<hr/>");
buffer.append(newMessage.getPosttime());
buffer.append("<p/>\r\n");
buffer.append(newMessage.getMessage());
buffer.append("<p><i>");
buffer.append(newMessage.getPerson().getName());
buffer.append("</i>");
}
person.writeMessage(buffer.toString());
// check mail
if (mailBean.hasNewMail(person))
{
person.writeMessage("<p>You have new Mudmail!</p>\r\n");
} else
{
person.writeMessage("<p>You have no new Mudmail...</p>\r\n");
}
// has guild
if (person.getGuild() != null)
{
// guild logonmessage
if (person.getGuild().getLogonmessage() != null)
{
person.writeMessage(person.getGuild().getLogonmessage()
+ "<hr/>");
}
// guild alarm message
person.writeMessage(person.getGuild().getAlarmDescription()
+ "<hr/>");
}
// write log "entered game."
logBean.writeLog(person, "entered game.");
// TODO : execute command "me has entered the game..." -> can be moved to the darned next ajax calls
} catch (WebApplicationException e)
{
//ignore
throw e;
} catch (MudException e)
{
throw new MudWebException(name, e, Response.Status.BAD_REQUEST);
} catch (PersistenceException e)
{
StringBuilder buffer = new StringBuilder("ConstraintViolationException:");
for (ConstraintViolation<?> violation : ((ConstraintViolationException) e.getCause()).getConstraintViolations())
{
buffer.append(violation);
}
throw new MudWebException(name, buffer.toString(), e, Response.Status.BAD_REQUEST);
} catch (ConstraintViolationException e)
{
StringBuilder buffer = new StringBuilder("ConstraintViolationException:");
for (ConstraintViolation<?> violation : e.getConstraintViolations())
{
buffer.append(violation);
}
throw new MudWebException(name, buffer.toString(), e, Response.Status.BAD_REQUEST);
}
}
/**
* Provides the player who is logged in during this session.
*
* @return name of the player
* @throws IllegalStateException
*/
protected String getPlayerName() throws IllegalStateException
{
final String name = context.getCallerPrincipal().getName();
if (name.equals("ANONYMOUS"))
{
throw new MudWebException(null, "Not logged in.", Response.Status.UNAUTHORIZED);
}
return name;
}
/**
* Main function for executing a command in the game.
*
* @param name the name of the player. Should match the authorized user.
* @param command the command issued
* @param offset the offset used for the log
* @param log indicates with true or false, whether or not we are
* interested in the log.
* @return NO_CONTENT if the game is offline for maintenance.
* @throws WebApplicationException BAD_REQUEST if an unexpected exception
* crops up or something could not be validated.
*/
@POST
@Path("{name}/play")
@Produces(
{
MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON
})
public PrivateDisplay playGame(@PathParam(value = "name") String name, String command, @QueryParam(value = "offset") Integer offset, @QueryParam(value = "log") boolean log) throws MudException
{
itsLog.entering(this.getClass().getName(), "playGame");
try
{
command = Utils.security(command);
} catch (PolicyException | ScanException ex)
{
throw new MudWebException(name, ex, Response.Status.BAD_REQUEST);
}
PrivateDisplay display = null;
User person = authenticate(name);
try
{
if (command.contains(" ; ") && (!command.toLowerCase().startsWith("macro ")))
{
// it's not a macro , but does contain multiple commands
display = runMultipleCommands(person, command);
} else
{
String[] parsedCommand = command.split(" ");
Macro macro = null;
if (parsedCommand.length <= 2 && (!command.toLowerCase().startsWith("macro ")))
{
// find macro (if it exists)
MacroPK pk = new MacroPK();
pk.setMacroname(parsedCommand[0]);
pk.setName(person.getName());
macro = getEntityManager().find(Macro.class, pk);
}
if (macro == null || macro.getContents() == null || macro.getContents().trim().equals(""))
{
// no macro found, execute single command
display = gameMain(person, command);
} else
{
// macro found, execute macro.
command = macro.getContents();
// macro
if (parsedCommand.length == 2)
{
command = command.replaceAll("%t", parsedCommand[1]);
}
display = runMultipleCommands(person, command);
}
}
} catch (WebApplicationException e)
{
itsLog.log(Level.INFO, "caught and rethrowing WebApplicationException {0} {1}", new Object[]
{
e.getClass().getName(), e.getMessage()
});
//ignore
throw e;
} catch (Throwable e)
{
Throwable f = e;
while (f.getCause() != null)
{
if (f.getCause() instanceof WebApplicationException)
{
throw (WebApplicationException) f.getCause();
}
f = f.getCause();
}
String message = (e.getMessage() == null || e.getMessage().trim().equals(""))
? "An error occurred. Please notify Karn or one of the deps."
: e.getMessage();
//ignore
throw new MudWebException(name, message, e, Response.Status.BAD_REQUEST);
}
// add log to the return value
if (log)
{
try
{
display.log = retrieveLog(person, offset);
} catch (MudException ex)
{
itsLog.throwing("play: throws ", ex.getMessage(), ex);
}
}
return display;
}
private PrivateDisplay runMultipleCommands(User person, String command)
throws MudException
{
PrivateDisplay result = null;
// multiple commands
String[] splitted = command.split(" ; ");
for (String str : splitted)
{
result = gameMain(person, str.trim());
}
return result;
}
/**
* It parses and executes the command of the
* user. The main batch of the server.
*
* @param person User who wishes to execute a command.
* @param command String containing the command entered
* @return PrivateDisplay containing the response.
* @throws MudException when something goes wrong.
*/
private PrivateDisplay gameMain(User person, String command) throws MudException
{
itsLog.log(Level.FINER, "{0}.gameMain", this.getClass().getName());
logBean.writeCommandLog(person, command);
if (CommandFactory.noUserCommands())
{
// get all user commands
itsLog.log(Level.FINER, "{0}.gameMain - get all user commands", this.getClass().getName());
Query query = getEntityManager().createNamedQuery("UserCommand.findActive");
List<UserCommand> list = query.getResultList();
for (UserCommand userCommand : list)
{
CommandFactory.addUserCommand(userCommand.getId(), userCommand.getCommand(), userCommand.getMethodName().getName(), (userCommand.getRoom() == null ? null : userCommand.getRoom().getId()));
}
}
List<UserCommandInfo> userCommands = CommandFactory.getUserCommands(person, command);
List<UserCommand> userCommands2 = new ArrayList<>();
if (!userCommands.isEmpty())
{
for (UserCommandInfo info : userCommands)
{
UserCommand com = getEntityManager().find(UserCommand.class, info.getCommandId());
if (com != null)
{
userCommands2.add(com);
}
}
}
DisplayInterface display = commandRunner.runCommand(person, command, userCommands2);
if (display == null || display == person.getRoom())
{
return createPrivateDisplayFromRoom(person);
}
return createPrivateDisplay(display, person);
}
private PrivateLog retrieveLog(Person person, Integer offset) throws MudException
{
if (offset == null)
{
offset = 0;
}
String log = person.getLog(offset);
PrivateLog plog = new PrivateLog();
plog.offset = offset;
plog.log = log;
plog.size = plog.log.length();
return plog;
}
/**
* Retrieves the log of a player.
*
* @param name the name of the user
* @param offset the offset from whence to read the log
* @return returns the log
* @see PrivateLog
* @throws WebApplicationException BAD_REQUEST if an unexpected exception
* crops up.
*/
@GET
@Path("{name}/log")
@Produces(
{
MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON
})
public PrivateLog getLog(@PathParam("name") String name, @QueryParam("offset") Integer offset)
{
itsLog.finer("entering retrieveLog");
Person person = authenticate(name);
if (offset == null)
{
offset = 0;
}
try
{
return retrieveLog(person, offset);
} catch (WebApplicationException e)
{
//ignore
throw e;
} catch (MudException e)
{
throw new MudWebException(name, e, Response.Status.BAD_REQUEST);
}
}
/**
* Removes the log of a player, i.e. creates a new empty log.
*
* @param name the name of the user
* @return Response.ok if everything's okay
* @throws WebApplicationException BAD_REQUEST if an unexpected exception
* crops up.
*/
@DELETE
@Path("{name}/log")
@Produces(
{
MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON
})
public Response deleteLog(@PathParam("name") String name)
{
itsLog.finer("entering deleteLog");
Person person = authenticate(name);
try
{
person.clearLog();
} catch (WebApplicationException e)
{
//ignore
throw e;
} catch (MudException e)
{
throw new MudWebException(name, e, Response.Status.BAD_REQUEST);
}
return Response.ok().build();
}
/**
* Stops a playing character from playing.
*
* @param name the name of the user
* @return An Ok response.
* @throws WebApplicationException BAD_REQUEST if an unexpected exception
* crops up.
*/
@GET
@Path("{name}/quit")
@Produces(
{
MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON
})
public Response quitGame(@PathParam("name") String name)
{
itsLog.finer("entering quit");
User person = authenticate(name);
try
{
person.getRoom().sendMessage(person, "%SNAME left the game.<BR>\r\n");
person.deactivate();
logBean.writeLog(person, "left the game.");
} catch (WebApplicationException e)
{
//ignore
throw e;
} catch (MudException e)
{
throw new MudWebException(name, e, Response.Status.BAD_REQUEST);
}
return Response.ok().build();
}
private PrivateDisplay createPrivateDisplay(DisplayInterface display, User player) throws MudException
{
PrivateDisplay result = new PrivateDisplay();
result.body = display.getBody();
result.image = display.getImage();
result.title = display.getMainTitle();
return result;
}
private PrivateDisplay createPrivateDisplayFromRoom(User player) throws MudException
{
PrivateDisplay result = createPrivateDisplay(player.getRoom(), player);
if (player.getRoom().getWest() != null)
{
result.west = true;
}
if (player.getRoom().getEast() != null)
{
result.east = true;
}
if (player.getRoom().getNorth() != null)
{
result.north = true;
}
if (player.getRoom().getSouth() != null)
{
result.south = true;
}
if (player.getRoom().getUp() != null)
{
result.up = true;
}
if (player.getRoom().getDown() != null)
{
result.down = true;
}
List<PrivatePerson> persons = new ArrayList<>();
for (Person person : player.getRoom().getPersons(player))
{
if (person.getVisible())
{
PrivatePerson pp = new PrivatePerson();
pp.race = person.getRace();
pp.name = person.getName();
persons.add(pp);
}
}
result.persons = persons;
result.items = Constants.addInventoryForRoom(player.getRoom().getItems());
return result;
}
@Override
public Room find(Integer id)
{
return getEntityManager().find(Room.class, id);
}
@Override
public String getAttribute(String name)
{
Worldattribute attribute = getEntityManager().find(Worldattribute.class, name);
if (attribute == null)
{
return null;
}
return attribute.getContents();
}
}