void ProtocolLogin::onRecv(InputMessage& inputMessage) { try { while(!inputMessage.eof()) { int opt = inputMessage.getU8(); switch(opt) { case Proto::LoginServerError: parseError(inputMessage); break; case Proto::LoginServerMotd: parseMOTD(inputMessage); break; case Proto::LoginServerUpdateNeeded: callLuaField("onError", "Client needs update."); break; case Proto::LoginServerCharacterList: parseCharacterList(inputMessage); break; default: Fw::throwException("unknown opt byte ", opt); break; } } } catch(Exception& e) { logTraceError(e.what()); } disconnect(); }
SoundFilePtr SoundFile::loadSoundFile(const std::string& filename) { FileStreamPtr file = g_resources.openFile(filename); if(!file) { logTraceError("unable to open ", filename); return nullptr; } // cache file buffer to avoid lags from hard drive file->cache(); char magic[4]; file->read(magic, 4); file->seek(0); SoundFilePtr soundFile; if(strncmp(magic, "OggS", 4) == 0) { OggSoundFilePtr oggSoundFile = OggSoundFilePtr(new OggSoundFile(file)); if(oggSoundFile->prepareOgg()) soundFile = oggSoundFile; } else logError("unknown sound file format ", filename); return soundFile; }
void UIWidget::lockChild(const UIWidgetPtr& child) { if(m_destroyed) return; if(!child) return; if(!hasChild(child)) { logTraceError("cannot find child"); return; } // prevent double locks if(isChildLocked(child)) unlockChild(child); // disable all other children for(const UIWidgetPtr& otherChild : m_children) { if(otherChild == child) child->setEnabled(true); else otherChild->setEnabled(false); } m_lockedChildren.push_front(child); // lock child focus if(child->isFocusable()) focusChild(child, Fw::ActiveFocusReason); }
int Thing::getStackpos() { if(m_position.x == 65535 && asItem()) // is inside a container return 0; else if(const TilePtr& tile = getTile()) return tile->getThingStackpos(asThing()); else { logTraceError("got a thing with invalid stackpos"); return -1; } }
void UIWidget::setStyle(const std::string& styleName) { OTMLNodePtr styleNode = g_ui.getStyle(styleName); if(!styleNode) { logTraceError("unable to retrive style '", styleName, "': not a defined style"); return; } applyStyle(styleNode); m_style = styleNode; updateStyle(); }
void ProtocolGame::parseCreatureMove(InputMessage& msg) { Position oldPos = parsePosition(msg); int oldStackpos = msg.getU8(); Position newPos = parsePosition(msg); ThingPtr thing = g_map.getTile(oldPos)->getThing(oldStackpos); if(!thing) { logTraceError("could not get thing"); return; } CreaturePtr creature = thing->asCreature(); if(!creature) { logTraceError("thing is not a creature"); return; } // update map tiles g_map.removeThing(thing); g_map.addThing(thing, newPos); g_game.processCreatureMove(creature, oldPos, newPos); }
void UIWidget::moveChildToIndex(const UIWidgetPtr& child, int index) { if(m_destroyed) return; if(!child) return; // remove and push child again auto it = std::find(m_children.begin(), m_children.end(), child); if(it == m_children.end()) { logTraceError("cannot find child"); return; } m_children.erase(it); m_children.insert(m_children.begin() + index - 1, child); updateChildrenIndexStates(); }
void UIWidget::raiseChild(UIWidgetPtr child) { if(m_destroyed) return; if(!child) return; // remove and push child again auto it = std::find(m_children.begin(), m_children.end(), child); if(it == m_children.end()) { logTraceError("cannot find child"); return; } m_children.erase(it); m_children.push_back(child); updateChildrenIndexStates(); }
void UIWidget::unlockChild(const UIWidgetPtr& child) { if(m_destroyed) return; if(!child) return; if(!hasChild(child)) { logTraceError("cannot find child"); return; } auto it = std::find(m_lockedChildren.begin(), m_lockedChildren.end(), child); if(it == m_lockedChildren.end()) return; m_lockedChildren.erase(it); // find new child to lock UIWidgetPtr lockedChild; if(m_lockedChildren.size() > 0) { lockedChild = m_lockedChildren.front(); assert(hasChild(lockedChild)); } for(const UIWidgetPtr& otherChild : m_children) { // lock new child if(lockedChild) { if(otherChild == lockedChild) lockedChild->setEnabled(true); else otherChild->setEnabled(false); } // else unlock all else otherChild->setEnabled(true); } if(lockedChild) { if(lockedChild->isFocusable()) focusChild(lockedChild, Fw::ActiveFocusReason); } }
void ProtocolGame::parseCreatureSpeak(InputMessage& msg) { msg.getU32(); // unkSpeak std::string name = msg.getString(); int level = msg.getU16(); int type = msg.getU8(); int channelId = 0; Position creaturePos; switch(type) { case Proto::SpeakSay: case Proto::SpeakWhisper: case Proto::SpeakYell: case Proto::SpeakMonsterSay: case Proto::SpeakMonsterYell: case Proto::SpeakPrivateNpcToPlayer: creaturePos = parsePosition(msg); break; case Proto::SpeakChannelYellow: case Proto::SpeakChannelWhite: case Proto::SpeakChannelRed: case Proto::SpeakChannelRed2: case Proto::SpeakChannelOrange: channelId = msg.getU16(); break; case Proto::SpeakPrivate: case Proto::SpeakPrivatePlayerToNpc: case Proto::SpeakBroadcast: case Proto::SpeakPrivateRed: break; case Proto::SpeakRVRChannel: msg.getU32(); break; default: logTraceError("unknown speak type ", type); break; } std::string message = msg.getString(); std::string typeDesc = Proto::translateSpeakType(type); g_game.processCreatureSpeak(name, level, typeDesc, message, channelId, creaturePos); }
void ProtocolGame::setTileDescription(InputMessage& msg, Position position) { g_map.cleanTile(position); int stackPos = 0; while(true) { int inspectTileId = msg.getU16(true); if(inspectTileId >= 0xFF00) return; else { if(stackPos >= 10) logTraceError("too many things, stackpos=", stackPos, " pos=", position); ThingPtr thing = internalGetThing(msg); if(thing) g_map.addThing(thing, position, 255); } stackPos++; } }
void UIWidget::insertChild(int index, const UIWidgetPtr& child) { if(!child) { logWarning("attempt to insert a null child into a UIWidget"); return; } if(hasChild(child)) { logWarning("attempt to insert a child again into a UIWidget"); return; } index = index <= 0 ? (m_children.size() + index) : index-1; if(!(index >= 0 && (uint)index <= m_children.size())) { logTraceError("attemp to insert a child in an invalid index"); return; } // retrieve child by index auto it = m_children.begin() + index; m_children.insert(it, child); child->setParent(asUIWidget()); // create default layout if needed if(!m_layout) m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(asUIWidget())); // add to layout and updates it m_layout->addWidget(child); // update new child states child->updateStates(); updateChildrenIndexStates(); g_ui.onWidgetAppear(child); }
void ProtocolGame::parseMessage(InputMessage& msg) { try { while(!msg.eof()) { int opt = msg.getU8(); switch(opt) { case Proto::GameServerInitGame: parsePlayerLogin(msg); break; case Proto::GameServerGMActions: parseGMActions(msg); break; case Proto::GameServerLoginError: parseLoginError(msg); break; case Proto::GameServerLoginAdvice: parseFYIMessage(msg); break; case Proto::GameServerLoginWait: parseWaitList(msg); break; case Proto::GameServerPing: parsePing(msg); break; //case Proto::GameServerChallange: case Proto::GameServerDead: parseDeath(msg); break; case Proto::GameServerFullMap: parseMapDescription(msg); break; case Proto::GameServerMapTopRow: parseMoveNorth(msg); break; case Proto::GameServerMapRightRow: parseMoveEast(msg); break; case Proto::GameServerMapBottomRow: parseMoveSouth(msg); break; case Proto::GameServerMapLeftRow: parseMoveWest(msg); break; case Proto::GameServerTileData: parseUpdateTile(msg); break; case Proto::GameServerCreateOnMap: parseTileAddThing(msg); break; case Proto::GameServerChangeOnMap: parseTileTransformThing(msg); break; case Proto::GameServerDeleteOnMap: parseTileRemoveThing(msg); break; case Proto::GameServerMoveCreature: parseCreatureMove(msg); break; case Proto::GameServerOpenContainer: parseOpenContainer(msg); break; case Proto::GameServerCloseContainer: parseCloseContainer(msg); break; case Proto::GameServerCreateContainer: parseContainerAddItem(msg); break; case Proto::GameServerChangeInContainer: parseContainerUpdateItem(msg); break; case Proto::GameServerDeleteInContainer: parseContainerRemoveItem(msg); break; case Proto::GameServerSetInventory: parseAddInventoryItem(msg); break; case Proto::GameServerDeleteInventory: parseRemoveInventoryItem(msg); break; case Proto::GameServerNpcOffer: parseOpenShopWindow(msg); break; case Proto::GameServerPlayerGoods: parsePlayerCash(msg); break; case Proto::GameServerCloseNpcTrade: parseCloseShopWindow(msg); break; case Proto::GameServerOwnOffer: parseSafeTradeRequest(msg); break; case Proto::GameServerCounterOffer: parseSafeTradeRequest(msg); break; case Proto::GameServerCloseTrade: parseSafeTradeClose(msg); break; case Proto::GameServerAmbient: parseWorldLight(msg); break; case Proto::GameServerGraphicalEffect: parseMagicEffect(msg); break; case Proto::GameServerTextEffect: parseAnimatedText(msg); break; case Proto::GameServerMissleEffect: parseDistanceMissile(msg); break; case Proto::GameServerMarkCreature: parseCreatureSquare(msg); break; //case Proto::GameServerTrappers case Proto::GameServerCreatureHealth: parseCreatureHealth(msg); break; case Proto::GameServerCreatureLight: parseCreatureLight(msg); break; case Proto::GameServerCreatureOutfit: parseCreatureOutfit(msg); break; case Proto::GameServerCreatureSpeed: parseCreatureSpeed(msg); break; case Proto::GameServerCreatureSkull: parseCreatureSkulls(msg); break; case Proto::GameServerCreatureParty: parseCreatureShields(msg); break; // case Proto::GameServerCreatureUnpass case Proto::GameServerEditText: parseItemTextWindow(msg); break; case Proto::GameServerEditList: parseHouseTextWindow(msg); break; case Proto::GameServerPlayerData: parsePlayerStats(msg); break; case Proto::GameServerPlayerSkills: parsePlayerSkills(msg); break; case Proto::GameServerPlayerState: parsePlayerIcons(msg); break; case Proto::GameServerClearTarget: parsePlayerCancelAttack(msg); break; //case Proto::GameServerSpellDelay: //case Proto::GameServerSpellGroupDelay: case Proto::GameServerTalk: parseCreatureSpeak(msg); break; case Proto::GameServerChannels: parseChannelList(msg); break; case Proto::GameServerOpenChannel: parseOpenChannel(msg); break; case Proto::GameServerPrivateChannel: parseOpenPrivatePlayerChat(msg); break; case Proto::GameServerRuleViolationChannel: msg.getU16(); break; case Proto::GameServerRuleViolationRemove: msg.getString(); break; case Proto::GameServerRuleViolationCancel: msg.getString(); break; case Proto::GameServerRuleViolationLock: break; case Proto::GameServerOpenOwnChannel: parseCreatePrivateChannel(msg); break; case Proto::GameServerCloseChannel: parseClosePrivateChannel(msg); break; case Proto::GameServerMessage: parseTextMessage(msg); break; case Proto::GameServerSnapBack: parseCancelWalk(msg); break; //case Proto::GameServerWait: case Proto::GameServerTopFloor: parseFloorChangeUp(msg); break; case Proto::GameServerBottomFloor: parseFloorChangeDown(msg); break; case Proto::GameServerOutfit: parseOutfitWindow(msg); break; case Proto::GameServerBuddyData: parseVipState(msg); break; case Proto::GameServerBuddyLogin: parseVipLogin(msg); break; case Proto::GameServerBuddyLogout: parseVipLogout(msg); break; case Proto::GameServerTutorialHint: parseShowTutorial(msg); break; case Proto::GameServerAutomapFlag: parseAddMarker(msg); break; case Proto::GameServerQuestLog: parseQuestList(msg); break; case Proto::GameServerQuestLine: parseQuestPartList(msg); break; //case Proto::GameServerChannelEvent: //case Proto::GameServerObjectInfo: //case Proto::GameServerPlayerInventory: default: Fw::throwException("unknown opt byte ", (int)opt); break; } } } catch(Exception& e) { logTraceError(e.what()); } }
ThingPtr ProtocolGame::internalGetThing(InputMessage& msg) { ThingPtr thing; int thingId = msg.getU16(); assert(thingId != 0); if(thingId == 0x0061 || thingId == 0x0062) { // add new creature CreaturePtr creature; if(thingId == 0x0062) { //creature is known uint id = msg.getU32(); CreaturePtr knownCreature = g_map.getCreatureById(id); if(knownCreature) creature = knownCreature; else logTraceError("server says creature is known, but its not on creatures list"); } else if(thingId == 0x0061) { //creature is not known uint removeId = msg.getU32(); uint id = msg.getU32(); std::string name = msg.getString(); if(name.length() > 0) // every creature name must start with a capital letter name[0] = toupper(name[0]); g_map.removeCreatureById(removeId); if(id == m_localPlayer->getId()) creature = m_localPlayer; else if(id >= Proto::PlayerStartId && id < Proto::PlayerEndId) creature = PlayerPtr(new Player); else if(id >= Proto::MonsterStartId && id < Proto::MonsterEndId) creature = MonsterPtr(new Monster); else if(id >= Proto::NpcStartId && id < Proto::NpcEndId) creature = NpcPtr(new Npc); else logTraceError("creature id is invalid"); creature->setId(id); creature->setName(name); } uint8 healthPercent = msg.getU8(); Otc::Direction direction = (Otc::Direction)msg.getU8(); Outfit outfit = internalGetOutfit(msg); Light light; light.intensity = msg.getU8(); light.color = msg.getU8(); int speed = msg.getU16(); int skull = msg.getU8(); int shield = msg.getU8(); int emblem = -1; if(thingId == 0x0061) // emblem is sent only in packet type 0x61 emblem = msg.getU8(); bool passable = (msg.getU8() == 0); if(creature) { creature->setHealthPercent(healthPercent); creature->setDirection(direction); creature->setOutfit(outfit); creature->setLight(light); creature->setSpeed(speed); creature->setSkull(skull); creature->setShield(shield); if(emblem != -1) creature->setEmblem(emblem); creature->setPassable(passable); creature->setDirection(direction); if(creature == m_localPlayer) { m_localPlayer->setKnown(true); } } thing = creature; } else if(thingId == 0x0063) { // creature turn parseCreatureTurn(msg); } else // item thing = internalGetItem(msg, thingId); return thing; }