/** * Copyright (C) 2002-2012 The FreeCol Team * * This file is part of FreeCol. * * FreeCol 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 2 of the License, or * (at your option) any later version. * * FreeCol 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 FreeCol. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.freecol.server.model; import java.util.Random; import java.util.logging.Logger; import net.sf.freecol.common.model.Building; import net.sf.freecol.common.model.BuildingType; import net.sf.freecol.common.model.Colony; import net.sf.freecol.common.model.Game; import net.sf.freecol.common.model.ModelMessage; import net.sf.freecol.common.model.StringTemplate; import net.sf.freecol.common.model.Unit; import net.sf.freecol.common.model.UnitType; import net.sf.freecol.server.control.ChangeSet; import net.sf.freecol.server.control.ChangeSet.See; /** * The server version of a building. */ public class ServerBuilding extends Building implements ServerModelObject { private static final Logger logger = Logger.getLogger(ServerBuilding.class.getName()); /** * Trivial constructor required for all ServerModelObjects. */ public ServerBuilding(Game game, String id) { super(game, id); } /** * Creates a new ServerBuilding. * * @param game The <code>Game</code> this object belongs to. * @param colony The <code>Colony</code> in which this building is located. * @param type The <code>BuildingType</code> of building. */ public ServerBuilding(Game game, Colony colony, BuildingType type) { super(game, colony, type); } /** * New turn for this building. * * @param random A <code>Random</code> number source. * @param cs A <code>ChangeSet</code> to update. */ public void csNewTurn(Random random, ChangeSet cs) { BuildingType type = getType(); ServerPlayer owner = (ServerPlayer) getColony().getOwner(); if (canTeach()) { teach(cs, owner); } if (type.hasAbility("model.ability.repairUnits")) { repairUnits(cs); } } private void teach(ChangeSet cs, ServerPlayer owner) { for (Unit teacher : getUnitList()) { boolean teacherDirty = false; boolean studentDirty = false; Unit student = teacher.getStudent(); if (student != null && student.getTeacher() != teacher) { // Sanitation, make sure we have the proper // teacher/student relation. logger.warning("Bogus teacher/student assignment."); teacher.setStudent(null); student = null; teacherDirty = true; } // Student may have changed if (student == null && csAssignStudent(teacher, cs)) { teacherDirty = true; studentDirty = true; student = teacher.getStudent(); } // Ready to train? if (student != null) { final int training = teacher.getTurnsOfTraining() + 1; if (training < teacher.getNeededTurnsOfTraining()) { teacher.setTurnsOfTraining(training); if (!teacherDirty) { cs.addPartial(See.only(owner), teacher, "turnsOfTraining"); } } else { StringTemplate oldName = student.getLabel(); UnitType teach = teacher.getType().getSkillTaught(); UnitType skill = Unit .getUnitTypeTeaching(teach, student.getType()); if (skill == null) { logger.warning("Student " + student.getId() + " can not learn from " + teacher.getId()); } else { student.setType(skill); StringTemplate newName = student.getLabel(); cs.addMessage(See.only(owner), new ModelMessage(ModelMessage.MessageType.UNIT_IMPROVED, "model.unit.unitEducated", getColony(), this) .addStringTemplate("%oldName%", oldName) .addStringTemplate("%unit%", newName) .addName("%colony%", getColony().getName())); } student.setTurnsOfTraining(0); student.setMovesLeft(0); cs.add(See.only(owner), student); studentDirty = false; teacher.setTurnsOfTraining(0); if (student.canBeStudent(teacher)) { // Keep teaching cs.addPartial(See.only(owner), teacher, "turnsOfTraining"); } else { student.setTeacher(null); teacher.setStudent(null); teacherDirty = true; if (csAssignStudent(teacher, cs)) { student = teacher.getStudent(); studentDirty = true; } } } } if (teacherDirty) cs.add(See.only(owner), teacher); if (studentDirty) cs.add(See.only(owner), student); } } /** * Assigns a student to a teacher within a building. * * @param teacher The <code>Unit</code> that is teaching. * @param cs A <code>ChangeSet</code> to update. */ private boolean csAssignStudent(Unit teacher, ChangeSet cs) { Colony colony = getColony(); final Unit student = colony.findStudent(teacher); if (student == null) { cs.addMessage(See.only((ServerPlayer) colony.getOwner()), new ModelMessage(ModelMessage.MessageType.WARNING, "model.building.noStudent", colony, teacher) .addStringTemplate("%teacher%", teacher.getLabel()) .addName("%colony%", colony.getName())); return false; } teacher.setStudent(student); teacher.setWorkType(null); student.setTeacher(teacher); return true; } private void repairUnits(ChangeSet cs) { for (Unit unit : getTile().getUnitList()) { if (unit.isUnderRepair() && getType().hasAbility("model.ability.repairUnits", unit.getType())) { ((ServerUnit) unit).csRepairUnit(cs); } } } /** * Returns the tag name of the root element representing this object. * * @return "serverBuilding" */ public String getServerXMLElementTagName() { return "serverBuilding"; } }