/* * Copyright 2014 The Skfiy Open Association. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.skfiy.typhon.spi.role; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import javax.inject.Inject; import org.skfiy.typhon.Typhons; import org.skfiy.typhon.domain.DailyTask; import org.skfiy.typhon.domain.Mail; import org.skfiy.typhon.domain.Normal; import org.skfiy.typhon.domain.Player; import org.skfiy.typhon.domain.Role; import org.skfiy.typhon.domain.RoleData; import org.skfiy.typhon.domain.item.MonthCardObject; import org.skfiy.typhon.session.SessionUtils; import org.skfiy.typhon.spi.RoleProvider; import org.skfiy.util.CustomizableThreadCreator; import org.skfiy.util.StringUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; /** * * @author Kevin Zou <kevinz@skfiy.org> */ public class NormalRoleDatable implements RoleDatable { private final ScheduledExecutorService REVIVAL_SCH_EXEC = Executors.newScheduledThreadPool(1, new ThreadFactory() { CustomizableThreadCreator threadCreator = new CustomizableThreadCreator("revigor-"); { threadCreator.setDaemon(true); } @Override public Thread newThread(Runnable r) { return threadCreator.createThread(r); } }); private final static String RESTORE_VIGOR = "_RESTOREVIGOR"; @Inject private RoleProvider roleProvider; @Override public void initialize(Player player) { Role role = player.getRole(); Normal normal = new Normal(); ExpLevel expLevel = roleProvider.getExpLevel(role.getLevel()); normal.setVigor(expLevel.getMaxVigor()); normal.setLastRevigorTime(System.currentTimeMillis()); role.setDiamond(Typhons.getInteger("typhon.spi.player.initDiamond")); normal.setCopper(Typhons.getInteger("typhon.spi.player.initCopper")); normal.setLastBuyDiamondTime(System.currentTimeMillis()); normal.setHornNum(Typhons.getInteger("typhon.spi.chat.world.hornNum")); normal.setFreeCount(5); normal.setVipLevel(Typhons.getInteger("typhon.spi.defaultVipLevel")); normal.setLastResetTime(System.currentTimeMillis()); MonthCardObject monthCardObject=new MonthCardObject(); normal.setMonthCardObject(monthCardObject); DailyTask dailyTask = new DailyTask(); normal.setDailyTask(dailyTask); player.setNormal(normal); role.setCreationTime(SessionUtils.getUser().getCreationTime()); // 注册监听器 normal.addPropertyChangeListener("vigor", new VigorChangeListener()); } @Override public void serialize(Player player, RoleData roleData) { roleData.setNormalData(JSON.toJSONString(player.getNormal(), // SerializerFeature.WriteClassName, SerializerFeature.DisableCircularReferenceDetect)); } @Override public void deserialize(RoleData roleData, Player player) { String data = roleData.getNormalData(); Normal normal; if (StringUtils.isEmpty(data)) { initialize(player); return; } else { normal = JSON.parseObject(data, Normal.class); } player.setNormal(normal); // ============================================================================== ExpLevel expLevel = roleProvider.getExpLevel(player.getRole().getLevel()); if (normal.getVigor() < expLevel.getMaxVigor()) { long rms = Typhons.getLong("typhon.spi.revigor.millis"); long s = System.currentTimeMillis() - normal.getLastRevigorTime(); int newVigor = (int) (normal.getVigor() + s / rms); // 如果恢复超过上限则只恢复到最大值 if (newVigor > expLevel.getMaxVigor()) { newVigor = expLevel.getMaxVigor(); } normal.setVigor(newVigor); normal.setLastRevigorTime(System.currentTimeMillis() - (s % rms)); if (newVigor < expLevel.getMaxVigor()) { RevigorTimerTask revigorTimerTask = new RevigorTimerTask(player); revigorTimerTask.schedule(); } } else { normal.setLastRevigorTime(System.currentTimeMillis()); } // ============================================================================== // 清理过期邮件 long currentTimeMillis = System.currentTimeMillis(); for (Mail mail : new ArrayList<>(normal.getMails())) { if (mail.getExpiredTime() > 0 && mail.getExpiredTime() <= currentTimeMillis) { normal.removeMail(mail); } } // 如果邮件超过上限则移除 int maxMailSize = Typhons.getInteger("typhon.spi.maxMailSize", 30); if (normal.getMailSize() > maxMailSize) { for (int i = 0; i < (normal.getMailSize() - maxMailSize); i++) { normal.removeMail(normal.getMail(i)); } } player.setNormal(normal); // 注册监听器 normal.addPropertyChangeListener("vigor", new VigorChangeListener()); } private class VigorChangeListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { Normal normal = (Normal) evt.getSource(); Player player = normal.player(); ExpLevel expLevel = roleProvider.getExpLevel(normal.getLevel()); if (expLevel.getMaxVigor() <= (int) evt.getOldValue() && expLevel.getMaxVigor() > (int) evt.getNewValue()) { normal.setLastRevigorTime(System.currentTimeMillis()); RevigorTimerTask revigorTimerTask = new RevigorTimerTask(player); revigorTimerTask.schedule(); } } } private class RevigorTimerTask implements Runnable { private final Player player; RevigorTimerTask(Player player) { this.player = player; } @Override public void run() { if (!player.getSession().isAvailable()) { return; } ExpLevel expLevel = roleProvider.getExpLevel(player.getRole().getLevel()); Normal normal = player.getNormal(); int maxVigor = expLevel.getMaxVigor(); int newVigor = normal.getVigor() + 1; if (newVigor <= maxVigor) { normal.setVigor(normal.getVigor() + 1); normal.setLastRevigorTime(System.currentTimeMillis()); } if (normal.getVigor() < maxVigor) { schedule(); } else { player.getSession().removeAttribute(RESTORE_VIGOR); } } public void schedule() { ScheduledFuture<?> future = (ScheduledFuture<?>) player.getSession().getAttribute(RESTORE_VIGOR); if (future != null) { future.cancel(true); } long rms = Typhons.getLong("typhon.spi.revigor.millis"); long delay = rms - (System.currentTimeMillis() - player.getNormal().getLastRevigorTime()); future = REVIVAL_SCH_EXEC.schedule(this, delay, TimeUnit.MILLISECONDS); player.getSession().setAttribute(RESTORE_VIGOR, future); } } }