/* * 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.lang.reflect.InvocationTargetException; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.logging.Logger; import javax.ejb.EJB; import javax.ejb.LocalBean; import javax.ejb.Schedule; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.script.ScriptException; import javax.ws.rs.core.Response; import mmud.database.entities.characters.Administrator; import mmud.database.entities.characters.User; import mmud.database.entities.game.Event; import mmud.database.entities.game.Method; import mmud.exceptions.MudWebException; import mmud.scripting.Items; import mmud.scripting.Persons; import mmud.scripting.Rooms; import mmud.scripting.RunScript; import mmud.scripting.World; /** * Takes care of all the events. * <img * src="doc-files/Eventsbean.png"> * * @startuml doc-files/Eventsbean.png * class EventsBean { * +events() * } * @enduml * @author maartenl */ @Stateless @LocalBean public class EventsBean { @EJB private PersonBean personBean; @EJB private GameBean gameBean; @EJB private ItemBean itemBean; @EJB private LogBean logBean; @PersistenceContext(unitName = "karchangamePU") private EntityManager em; /** * 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(EventsBean.class.getName()); /** * Runs a single event, right now. Used by administrators for testing. * * @param aUser the administrator running the event * @param eventid an event id, a number. */ public void runSingleEvent(Administrator aUser, Integer eventid) { itsLog.entering(this.getClass().getName(), "runSingleEvent"); if (eventid == null) { throw new MudWebException(null, "Event id was empty.", Response.Status.BAD_REQUEST); } Event event = getEntityManager().find(Event.class, eventid); if (event == null) { throw new MudWebException(null, "Event was not found.", Response.Status.NOT_FOUND); } Persons persons = new Persons(personBean); Rooms rooms = new Rooms(gameBean); Items items = new Items(itemBean); World world = new World(gameBean); RunScript runScript = new RunScript(persons, rooms, items, world); Method method = event.getMethod(); try { if (event.getRoom() != null) { boolean result = runScript.run(event.getRoom(), method.getSrc()); } else if (event.getPerson() != null) { boolean result = runScript.run(event.getPerson(), method.getSrc()); } else { boolean result = runScript.run(method.getSrc()); } } catch (InvocationTargetException | InstantiationException | IllegalAccessException | ScriptException | NoSuchMethodException ex) { // Error occurred: turn this event off! // TODO: that's for debugging,... // event.setCallable(Boolean.FALSE); // log it but keep going with the next event. logBean.writeLogException(ex); itsLog.throwing(EventsBean.class.getName(), "events()", ex); throw new MudWebException(aUser.getName(), ex.getMessage(), ex, Response.Status.BAD_REQUEST); } } /** * Runs every minute, looks up which user-defined event to execute now. * So, this takes care of the events that have been dictates by the deputies. * * @throws java.lang.IllegalAccessException * @throws java.lang.InstantiationException * @throws java.lang.reflect.InvocationTargetException */ @Schedule(hour = "*", minute = "*/1") public void events() throws IllegalAccessException, InstantiationException, InvocationTargetException { // itsLog.log(Level.INFO, "Events scheduled at time {0}.", new Date()); // logBean.writeLog(null, "Events scheduled at time " + new Date() + "."); Query query = getEntityManager().createNamedQuery("Event.list"); Calendar calendar = Calendar.getInstance(); query.setParameter("month", calendar.get(Calendar.MONTH)); query.setParameter("dayofmonth", calendar.get(Calendar.DAY_OF_MONTH)); query.setParameter("dayofweek", calendar.get(Calendar.DAY_OF_WEEK)); query.setParameter("hour", calendar.get(Calendar.HOUR_OF_DAY)); query.setParameter("minute", calendar.get(Calendar.MINUTE)); List<Event> list = query.getResultList(); Persons persons = new Persons(personBean); Rooms rooms = new Rooms(gameBean); Items items = new Items(itemBean); World world = new World(gameBean); RunScript runScript = new RunScript(persons, rooms, items, world); for (Event event : list) { // itsLog.log(Level.INFO, "Event {0} executed.", event.getEventid()); logBean.writeLog("Event " + event.getEventid() + " executed."); Method method = event.getMethod(); try { if (event.getRoom() != null) { boolean result = runScript.run(event.getRoom(), method.getSrc()); } else if (event.getPerson() != null) { boolean result = runScript.run(event.getPerson(), method.getSrc()); } else { boolean result = runScript.run(method.getSrc()); } } catch (ScriptException | NoSuchMethodException ex) { // Error occurred: turn this event off! // TODO: that's for debugging,... // event.setCallable(Boolean.FALSE); // log it but keep going with the next event. logBean.writeLogException(ex); itsLog.throwing(EventsBean.class.getName(), "events()", ex); } } } // TODO : scheduler that cleans up people, runs at midnight // TODO : scheduler that increments item durability, runs at high noon? // TODO : fighting scheduler (second = "*/2") /** * Started once an hour, and computes who has been idle too long. */ @Schedule(hour = "*", minute = "1") private void executeIdleCleanup() { logBean.writeLog("executeIdleCleanup(): scheduled at time " + new Date() + "."); Query query = getEntityManager().createNamedQuery("User.who"); List<User> list = query.getResultList(); for (User user : list) { if (user.isIdleTooLong()) { final String message = "executeIdleCleanup(): " + user.getName() + " was idle for " + user.getIdleTime() + " minutes. Deactivated."; itsLog.info(message); logBean.writeLog(message); user.getRoom().sendMessageExcl(user, "%SNAME fade%VERB2 slowly from existence.<br/>\r\n"); user.deactivate(); } } } }