/* * skillcache.cpp * * Copyright (C) 2006 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * 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 (version 2 of the License) * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include "util/skillcache.h" #include "net/message.h" //------------------------------------------------------------------- int count = 0; psSkillCacheItem::psSkillCacheItem(psSkillCacheItem *item) : removed(false), modified(true) { skillId = item->skillId; nameId = item->nameId; removed = item->removed; if (!removed) { rank = item->rank; actualStat = item->actualStat; knowledge = item->knowledge; knowledgeCost = item->knowledgeCost; practice = item->practice; practiceCost = item->practiceCost; category = item->category; stat = item->stat; } } psSkillCacheItem::psSkillCacheItem(unsigned int nameId) : removed(false), modified(true) { this->nameId = nameId; this->skillId = nameId; } psSkillCacheItem::psSkillCacheItem(int skillId, unsigned int nameId, unsigned short R, unsigned short AS, unsigned short Y, unsigned short YC, unsigned short Z, unsigned short ZC, unsigned short CAT, bool stat) : removed(false), modified(true) { this->skillId = skillId; this->nameId = nameId; rank = R; actualStat = AS; knowledge = Y; knowledgeCost = YC; practice = Z; practiceCost = ZC; category = CAT; this->stat = stat; modified = true; } psSkillCacheItem::~psSkillCacheItem() { } unsigned short psSkillCacheItem::size() const { if (removed) return sizeof(uint8_t); else return sizeof(uint8_t) + 7*sizeof(uint16_t) + sizeof(bool); } void psSkillCacheItem::update(unsigned short R, unsigned short AS, unsigned short Y, unsigned short YC, unsigned short Z, unsigned short ZC) { if (rank != R) { rank = R; modified = true; } if (actualStat != AS) { actualStat = AS; modified = true; } if (knowledge != Y) { knowledge = Y; modified = true; } if (knowledgeCost != YC) { knowledgeCost = YC; modified = true; } if (practice != Z) { practice = Z; modified = true; } if (practiceCost != ZC) { practiceCost = ZC; modified = true; } } void psSkillCacheItem::update(psSkillCacheItem *item) { if (rank != item->rank) { rank = item->rank; modified = true; } if (actualStat != item->actualStat) { actualStat = item->actualStat; modified = true; } if (knowledge != item->knowledge) { knowledge = item->knowledge; modified = true; } if (knowledgeCost != item->knowledgeCost) { knowledgeCost = item->knowledgeCost; modified = true; } if (practice != item->practice) { practice = item->practice; modified = true; } if (practiceCost != item->practiceCost) { practiceCost = item->practiceCost; modified = true; } } void psSkillCacheItem::read(MsgEntry *msg) { psSkillCacheItem::Oper op = (psSkillCacheItem::Oper)msg->GetUInt8(); switch (op) { case psSkillCacheItem::REMOVE: removed = true; break; case psSkillCacheItem::UPDATE_OR_ADD: rank = msg->GetUInt16(); actualStat = msg->GetUInt16(); knowledge = msg->GetUInt16(); knowledgeCost = msg->GetUInt16(); practice = msg->GetUInt16(); practiceCost = msg->GetUInt16(); category = msg->GetUInt16(); stat = msg->GetBool(); break; } modified = true; } void psSkillCacheItem::write(MsgEntry *msg) { if (removed) { msg->Add((uint8_t)psSkillCacheItem::REMOVE); } else { msg->Add((uint8_t)psSkillCacheItem::UPDATE_OR_ADD); msg->Add((uint16_t)rank); msg->Add((uint16_t)actualStat); msg->Add((uint16_t)knowledge); msg->Add((uint16_t)knowledgeCost); msg->Add((uint16_t)practice); msg->Add((uint16_t)practiceCost); msg->Add((uint16_t)category); msg->Add(stat); } modified = false; } //------------------------------------------------------------------- psSkillCache::psSkillCache() : modified(false), newList(false), progressionPoints(0) { } psSkillCache::~psSkillCache() { clear(); } void psSkillCache::clear() { while (!skillCache.IsEmpty()) { delete skillCache.Front(); skillCache.PopFront(); } } void psSkillCache::apply(psSkillCache *list) { // If this is a completely new list of skills, clear own internal cache if (list->isNew()) clear(); newList = list->newList; progressionPoints = list->progressionPoints; // Apply individual cache items in the received list of skills psSkillCacheIter p = list->iterBegin(); while (p.HasNext()) { psSkillCacheItem *second = p.Next(); psSkillCacheItem *item = getItemBySkillId(second->getSkillId()); if (second->isRemoved()) { // If the skill was removed, remove from the cache if (item) { deleteItem(item); modified = true; } } else { // Otherwise either update or add to the cache if (item) { item->update(second); } else { item = new psSkillCacheItem(second); skillCache.PushBack(item); } } } modified = true; } void psSkillCache::addItem(int skillId, psSkillCacheItem *item) { skillCache.PushBack(item); } psSkillCacheItem *psSkillCache::getItemBySkillId(int id) { psSkillCacheIter p(skillCache); while (p.HasNext()) { psSkillCacheItem *item = p.Next(); if (item && item->getSkillId() == id) return item; } return NULL; } void psSkillCache::setModified(bool modified) { modified = modified; psSkillCacheIter p(skillCache); while (p.HasNext()) { psSkillCacheItem *item = p.Next(); if (item) item->setModified(modified); } } bool psSkillCache::isModified() { if (modified) return true; psSkillCacheIter p(skillCache); while (!modified && p.HasNext()) { psSkillCacheItem *item = p.Next(); if (item && item->isModified()) return true; } return false; } void psSkillCache::setProgressionPoints(unsigned int points) { if (points != progressionPoints) { progressionPoints = points; modified = true; } } unsigned short psSkillCache::size() const { unsigned short sz = sizeof(uint32_t) + sizeof(bool) + sizeof(uint16_t); psSkillCacheIter p(skillCache); while (p.HasNext()) { psSkillCacheItem *item = p.Next(); if (item && item->isModified()) sz += item->size() + sizeof(uint32_t); } return sz; } unsigned short psSkillCache::count() const { unsigned short cnt = 0; psSkillCacheIter p(skillCache); while (p.HasNext()) { psSkillCacheItem *item = p.Next(); if (item && item->isModified()) ++cnt; } return cnt; } void psSkillCache::read(MsgEntry *msg) { unsigned short count; progressionPoints = msg->GetUInt32(); newList = msg->GetBool(); count = msg->GetUInt16(); for (int i = 0; i < count; i++) { unsigned int nameId; psSkillCacheItem *item; nameId = msg->GetUInt32(); if ((item = getItemBySkillId(nameId)) == NULL) { item = new psSkillCacheItem(nameId); skillCache.PushBack(item); } item->read(msg); } modified = true; } void psSkillCache::write(MsgEntry *msg) { msg->Add((uint32_t)progressionPoints); msg->Add(newList); unsigned short cnt = count(); msg->Add((uint16_t)cnt); // Iterate through the list psSkillCacheIter p(skillCache); psSkillCacheItem *item = NULL; if (p.HasNext()) item = p.Next(); while (item) { if (item->isModified()) { // Add modified skills to the message msg->Add(item->getNameId()); item->write(msg); if (item->isRemoved()) { // Remove skills that were marked for removal skillCache.Delete(p); delete item; if (p.HasCurrent()) item = p.FetchCurrent(); else item = NULL; continue; } } if (p.HasNext()) item = p.Next(); else item = NULL; } newList = false; modified = false; } bool psSkillCache::deleteItem(psSkillCacheItem *item) { psSkillCacheIter p(skillCache); while (p.HasNext()) { if (p.Next() == item) { skillCache.Delete(p); delete item; return true; } } return false; }