bool Universe::Run() { bool continueFlag; //Continue game or not char inPacket[256]; //Holds the input packet char outPacket[256]; //Holds the output packet int iResult; //The result of 'Receive' and 'Send' continueFlag = true; connectSocket = new ClientSocket(serverAddress, serverPort); printf("Connected to the server\n"); CreatePacket(outPacket, LogIn, "%s%s", login, password); connectSocket->Send(outPacket); game = NULL; currentCharacter = NULL; ClientGUIInit(); //variables for camera cameraY = 50.0f; ISceneNode* camPos=render->smgr->addEmptySceneNode(); camPos->setPosition(vector3df(50.0f,cameraY,10.0f)); camera=render->smgr->addCameraSceneNode(NULL, vector3df(50.0f, 50.0f, 10.0f), vector3df(50.0f, 0.0f, 40.0f)); scene::ISceneNode* lnode; lnode = render->smgr->addLightSceneNode(NULL, camPos->getPosition(), video::SColorf(1.0f, 1.0f, 1.0f, 1.0f), 800.0f); render->smgr->setAmbientLight(video::SColor(0, 60, 60, 60)); state = Continue; int lastUpdate = render->device->getTimer()->getTime(); while (render->device->run() && state == Continue) { //Receving packet from the server iResult = connectSocket->Receive(inPacket); if (iResult) { if (iResult > 0) { //Packet received switch (GetPacketType(inPacket)) { case LoggedIn: char gameName[256]; int locationId; ScanPacket(inPacket, "%s%i", gameName, &locationId); game = new Game(gameName, Client); printf("Game %s initialized\n", game->name); currentLocation = game->data->GetLocation(locationId); DrawScene(); break; case NPCSpawned: currentLocation->SpawnNPC(new CurrentNPC(inPacket)); break; case StaticSpawned: { CurrentStatic* currentStatic = new CurrentStatic(inPacket); currentLocation->SpawnStatic(currentStatic); break; } case ItemSpawned: char spawnType; //TODO: SpawnType as char ScanPacket(inPacket, "%i%i%f%f%b", NULL, NULL, NULL, NULL, &spawnType); switch(spawnType) { case Ground: currentLocation->SpawnItem(new CurrentItem(inPacket)); break; case Inventory: currentCharacter->SpawnItem(new CurrentItem(inPacket)); break; } break; case CharacterSpawned: if (!currentCharacter) { currentCharacter = new CurrentCharacter(inPacket); currentLocation->SpawnCharacter(currentCharacter); } else { currentLocation->SpawnCharacter(new CurrentCharacter(inPacket)); } break; case SkillSpawned: currentCharacter->SpawnSkill(new CurrentSkill(inPacket)); break; case NPCUnspawned: currentLocation->UnSpawnNPC(currentLocation->GetNPC(PacketGetInt(inPacket, 1))); break; case StaticUnspawned: currentLocation->UnSpawnStatic(currentLocation->GetStatic(PacketGetInt(inPacket, 1))); break; case ItemUnspawned: switch(PacketGetByte(inPacket, 5)) { case Ground: currentLocation->UnSpawnItem(currentLocation->GetItem(PacketGetInt(inPacket, 1))); break; case Inventory: //currentCharacter->UnSpawnItem(currentCharacter->GetItem(PacketGetInt(inPacket, 1))); break; } break; case CharacterUnspawned: currentLocation->UnSpawnCharacter(currentLocation->GetCharacter(PacketGetInt(inPacket, 1))); break; case Say: { IGUIElement* eb = guienv->getRootGUIElement()->getElementFromId(ChatBox)->getElementFromId(ChatEditBox); char messageType; //TODO: MessageType as char int senderCurrentCharacterId; wchar_t messageText[CHAT_MESSAGE_MAX_LENGTH]; ScanPacket(inPacket, "%b%i%ws", &messageType, &senderCurrentCharacterId, messageText); CurrentCharacter* sender = game->data->GetCharacter(senderCurrentCharacterId); wchar_t wLogin[64]; mbstowcs(wLogin, sender->login, 63); int offset = wcslen(eb->getText()) + wcslen(wLogin) + wcslen(messageText) + 3 - (CHAT_MAX_LENGTH - 1); if (offset < 0) offset = 0; else if (offset >= CHAT_MAX_LENGTH) offset = CHAT_MAX_LENGTH - 1; wchar_t wstr[CHAT_MAX_LENGTH]; swprintf(wstr, L"%ls\n%ls: %ls", eb->getText() + offset, wLogin, messageText); eb->setText(wstr); //delete wstr; break; } case CharacterMoving: { int currentCharacterId; f32 x, y; ScanPacket(inPacket, "%i%f%f", ¤tCharacterId, &x, &y); CurrentCharacter* movingCurrentCharacter = currentLocation->GetCharacter(currentCharacterId); movingCurrentCharacter->setAnimation(EMAT_RUN); render->moveNode(movingCurrentCharacter->node, vector3df(x * CELL_SIZE, 0, y * CELL_SIZE), movingCurrentCharacter->base->speed); //TEST movingCurrentCharacter->x = x; movingCurrentCharacter->y = y; break; } case HpChanged: { int characterId, changedHp; CurrentCharacter *character; ScanPacket(inPacket, "%i%i", &characterId, &changedHp); if (character = currentLocation->GetCharacter(characterId)) character->hp = changedHp; break; } case CharacterDied: { //okay break; } case CharacterMoved: { int characterId; f32 whereX, whereY; ScanPacket(inPacket, "%i%f%f", &characterId, &whereX, &whereY); printf("CLIENT CHAR ID: %d\n", characterId); printf("CLIENT WHERE X: %.f\n", whereX); printf("CLIENT WHERE Y: %.f\n", whereY); CurrentCharacter *character = currentLocation->GetCharacter(characterId); if (character) { printf("CLIENT TEST 1\n"); //character->node->setPosition(vector3df(whereX * CELL_SIZE, character->node->getPosition().Y, whereY * CELL_SIZE)); //TODO: Why setPosition is not working?!! render->moveNode(character->node, vector3df(whereX * CELL_SIZE, character->node->getPosition().Y, whereY * CELL_SIZE), 1000000.0f); printf("CLIENT TEST 2\n"); character->x = whereX; character->y = whereY; } break; } case DialogOpened: { char title[256]; char text[4096]; wchar_t wstr[512]; //npcID = PacketGetInt(inPacket, 1); //strcpy(title, PacketGetString(inPacket, 5)); sprintf(title, "[%d] %s", PacketGetInt(inPacket, 1), PacketGetString(inPacket, 5)); strcpy(text, PacketGetString(inPacket, strlen(PacketGetString(inPacket, 5)) + 5 + 1)); mbstowcs(wstr, title, 255); IGUIWindow* wnd = guienv->addWindow(rect<s32>(256, 128, 256 + 256, 128 + 320), false, wstr, NULL, -1); char patterns[][256] = { "<p\\s+rect\\s*=\\s*\\\"(.*?);(.*?);(.*?);(.*?)\\\">(.*?)</p>", "<button\\s+rect\\s*=\\s*\\\"(.*?);(.*?);(.*?);(.*?)\\\"\\s+onclick\\s*=\\s*\\\"(.*?)\\\">(.*?)</button>", /* "<p>(.*?)</p>", "<p>(.*?)</p>", "<p>(.*?)</p>",*/ }; char** result; int patternsCount = 2; const char *error; int erroffset; int count; int ovector[30]; const unsigned char *tables = NULL; tables = pcre_maketables(); for (int i = 0; i < patternsCount; i++) { pcre *re = pcre_compile ((char*)patterns[i], 0, &error, &erroffset, NULL); count = pcre_exec(re, NULL, (char*)text, strlen(text), 0, NULL, ovector, 30); if (count > 0) { result = new char*[count]; for (int c = 0; c < 2 * count; c += 2) { if (ovector[c] >= 0) { result[c / 2] = new char[ovector[c + 1] - ovector[c] + 1]; memcpy(result[c / 2], text + ovector[c], ovector[c + 1] - ovector[c]); result[c / 2][ovector[c + 1] - ovector[c]] = '\0'; //printf("%d, %d\n", ovector[c], ovector[c + 1]); //printf("%s\n", result[c / 2]); } else { result[c / 2] = NULL; } } switch (i) { case 0: //p { wchar_t wstr[1024]; mbstowcs(wstr, result[5], 1023); guienv->addStaticText(wstr, rect<s32>(atoi(result[1]), atoi(result[2]), atoi(result[1]) + atoi(result[3]), atoi(result[2]) + atoi(result[4])), false, true, wnd, DialogElement, false); break; } case 1: //button { wchar_t wstr[256]; mbstowcs(wstr, result[6], 255); guienv->addButton(rect<s32>(atoi(result[1]), atoi(result[2]), atoi(result[1]) + atoi(result[3]), atoi(result[2]) + atoi(result[4])), wnd, DialogElement + atoi(result[5]), wstr, NULL); break; } } for (int j = 0; j < count; j++) if (result[j]) delete result[j]; delete result; } } break; } case PlayEffect: { CurrentMapObject<MapObject>* currentMapObject; int currentMapObjectId = PacketGetInt(inPacket, 2); int skillId = PacketGetInt(inPacket, 6); switch (PacketGetByte(inPacket, 1)) { case 0: //NPC currentMapObject = (CurrentMapObject<MapObject>*)currentLocation->GetNPC(currentMapObjectId); break; case 3: //Character currentMapObject = (CurrentMapObject<MapObject>*)currentLocation->GetCharacter(currentMapObjectId); break; } render->PlayEffect(currentMapObject->node, game->resources->GetSkill(skillId)->effectTextures); break; } case PlayAdvancedEffect: int skillId = PacketGetInt(inPacket, 1); f32 xStart = PacketGetInt(inPacket, 5) * CELL_SIZE; f32 yStart = PacketGetInt(inPacket, 9) * CELL_SIZE; f32 xEnd = PacketGetInt(inPacket, 13) * CELL_SIZE; f32 yEnd = PacketGetInt(inPacket, 17) * CELL_SIZE; render->Effect2(vector3df(xStart, 5.0f, yStart), vector3df(xEnd, 5.0f, yEnd)); //TEST break; } } else if (iResult == -1) { //Disconnected from the server printf("Disconnected from the server\n"); delete Universe::instance->login; delete Universe::instance->password; Universe::instance->login = NULL; Universe::instance->password = NULL; Universe::instance->state = NextLevel; } else { //Wrong packet from the client printf("Warning! Wrong packet from server. Error code: %d\n", iResult); } } //Drawing if ((render->device->getTimer()->getTime() - lastUpdate) > 30) { lastUpdate = render->device->getTimer()->getTime(); if (game) { if (currentCharacter) { render->Km = camPos->getPosition(); render->Kt = camera->getTarget(); //Kt.X = currentCharacter->x * CELL_SIZE; //Kt.Z = currentCharacter->y * CELL_SIZE; vector3df pos = currentCharacter->node->getPosition(); render->Kt.X = pos.X; render->Kt.Z = pos.Z; render->Km.X = render->Kt.X; render->Km.Z = render->Kt.Z - 30; render->Km.Y = cameraY; camera->setPosition(render->Km); camera->setTarget(render->Kt); //vector3df lPos = camera->getPosition(); vector3df lPos = currentCharacter->node->getPosition(); lPos.Y = 15; //lPos.Z += 20; lnode->setPosition(lPos); } render->driver->beginScene(true, true, SColor(255,100,101,140)); render->smgr->drawAll(); guienv->drawAll(); render->driver->endScene(); } } } ClientGUIDestroy(); delete connectSocket; if (game) { delete game; render->smgr->clear(); } if (state == NextLevel) return false; return true; }
bool ClientEventReceiver::OnEvent(const SEvent& event) { if (event.EventType == irr::EET_KEY_INPUT_EVENT) { KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; if (event.KeyInput.Key >= KEY_KEY_1 && event.KeyInput.Key <= KEY_KEY_9) { if (Universe::instance->guienv->getFocus() != Universe::instance->guienv->getRootGUIElement()->getElementFromId(ChatBox)->getElementFromId(ChatInputEditBox)) { IGUIElement* hkb = Universe::instance->guienv->getRootGUIElement()->getElementFromId(HotkeyBar); CGUIButton* btn = ((IGUIIconTable*)hkb)->getButtonAt(event.KeyInput.Key - KEY_KEY_1); if (btn) { SEvent clickEvent; clickEvent.EventType = EET_GUI_EVENT; clickEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED; clickEvent.GUIEvent.Caller = btn; Universe::instance->render->device->postEventFromUser(clickEvent); } } } else if (KeyIsDown[KEY_ESCAPE]) { //Return to the main menu delete Universe::instance->login; delete Universe::instance->password; Universe::instance->login = NULL; Universe::instance->password = NULL; Universe::instance->state = NextLevel; } else if (KeyIsDown[KEY_RETURN]) { Universe::instance->guienv->setFocus(Universe::instance->guienv->getRootGUIElement()->getElementFromId(ChatBox)->getElementFromId(ChatInputEditBox)); } } else if(event.EventType == irr::EET_MOUSE_INPUT_EVENT) { for (s32 i = 0; i < EMIE_COUNT; ++i) Mouse[i] = i == event.MouseInput.Event; IGUIElement* guiElement = Universe::instance->guienv->getRootGUIElement()->getElementFromPoint(vector2di(event.MouseInput.X, event.MouseInput.Y)); if (guiElement != NULL) { //Mouse is in a window area if (guiElement->getID() != 0) //Mouse is on GUI element return false; } else //Mouse is not in a window area return false; if (Mouse[EMIE_LMOUSE_PRESSED_DOWN]) { CurrentMapObject<MapObject>* targetCurrentMapObject; CGUIButton* leftMouseBind = ((IGUIIconTable*)Universe::instance->guienv->getRootGUIElement()->getElementFromId(HotkeyBar))->selectedButton; if (leftMouseBind) { int targetType; char outPacket[256]; if (targetCurrentMapObject = (CurrentMapObject<MapObject>*)Universe::instance->render->GetCurrentMapObjectUnderCursor<CurrentNPC>(Universe::instance->currentLocation->currentNPCs, Universe::instance->currentLocation->currentNPCsCount)) { targetType = 0; } else if (targetCurrentMapObject = (CurrentMapObject<MapObject>*)Universe::instance->render->GetCurrentMapObjectUnderCursor<CurrentCharacter>(Universe::instance->currentLocation->currentCharacters, Universe::instance->currentLocation->currentCharactersCount)) { targetType = 3; } else targetType = -1; CreatePacket(outPacket, SkillUse, "%i%b%i", leftMouseBind->currentGameObject->id, targetType, targetCurrentMapObject ? targetCurrentMapObject->id : 0); Universe::instance->connectSocket->Send(outPacket); } } else if (Mouse[EMIE_RMOUSE_PRESSED_DOWN]) { CurrentMapObject<MapObject>* targetCurrentMapObject; if (targetCurrentMapObject = (CurrentMapObject<MapObject>*)Universe::instance->render->GetCurrentMapObjectUnderCursor<CurrentNPC>(Universe::instance->currentLocation->currentNPCs, Universe::instance->currentLocation->currentNPCsCount)) { char outPacket[256]; CreatePacket(outPacket, DialogOpen, "%i%i", targetCurrentMapObject->id, 0); Universe::instance->connectSocket->Send(outPacket); } else if (targetCurrentMapObject = (CurrentMapObject<MapObject>*)Universe::instance->render->GetCurrentMapObjectUnderCursor<CurrentItem>(Universe::instance->currentLocation->currentItems, Universe::instance->currentLocation->currentItemsCount)) { char outPacket[256]; f32 distance = vector2d<f32>(targetCurrentMapObject->x, targetCurrentMapObject->y).getDistanceFrom(vector2d<f32>(Universe::instance->currentCharacter->x, Universe::instance->currentCharacter->y)); if (distance < 3.0f) { CreatePacket(outPacket, ItemPickUp, "%i", targetCurrentMapObject->id); } else { //Emulate character's move request to this item double targetX, targetY; //TODO: other angles targetX = targetCurrentMapObject->x + (targetCurrentMapObject->x < Universe::instance->currentCharacter->x ? 1.0f : -1.0f); targetY = targetCurrentMapObject->y + (targetCurrentMapObject->y < Universe::instance->currentCharacter->y ? 1.0f : -1.0f); CreatePacket(outPacket, Move, "%f%f", targetX, targetY); } Universe::instance->connectSocket->Send(outPacket); } else { //Move char outPacket[256]; vector2d<f32> clickPos = Universe::instance->render->MouseCoordToWorldCoord(); if (clickPos.X > 0 && clickPos.X < Universe::instance->currentLocation->width && clickPos.Y > 0 && clickPos.Y < Universe::instance->currentLocation->height) if (Universe::instance->currentLocation->mask[(int)clickPos.Y][(int)clickPos.X] == Free) //TODO: see 'void Location::SpawnStatic(CurrentStatic* currentStatic)' { CreatePacket(outPacket, Move, "%f%f", clickPos.X, clickPos.Y); Universe::instance->connectSocket->Send(outPacket); } } } else if (Mouse[EMIE_MOUSE_WHEEL]) { f32 cameraNextY = Universe::instance->cameraY + event.MouseInput.Wheel * 5.0f; if (cameraNextY > 5.0f && cameraNextY < 200.0f) Universe::instance->cameraY = cameraNextY; } } else if (event.EventType == EET_GUI_EVENT) { s32 eventCallerId = event.GUIEvent.Caller->getID(); IGUIElement* eventCaller = event.GUIEvent.Caller; switch(event.GUIEvent.EventType) { case RPGATOR_EET_ELEMENT_DRAGGED: if (event.GUIEvent.Element) { //Element dragged to an GUI element if (event.GUIEvent.Element->getParent()) { //Element dragged to an GUI element that has parent (IGUIIconTableContainer) if (event.GUIEvent.Element->getParent()->getID() == HotkeyBar) { //Empty cell CGUIButton* hotkeyButton = new CGUIButton(*((CGUIButton*)event.GUIEvent.Caller)); ((IGUIIconTable::IGUIIconTableContainer*)event.GUIEvent.Element)->setButton(hotkeyButton); } else if (event.GUIEvent.Element->getParent()->getParent()) { //Element dragged to an GUI element that has parent (IGUIIconTable) if (event.GUIEvent.Element->getParent()->getParent()->getID() == HotkeyBar) { //Existing cell CGUIButton* hotkeyButton = new CGUIButton(*((CGUIButton*)event.GUIEvent.Caller)); ((IGUIIconTable::IGUIIconTableContainer*)event.GUIEvent.Element->getParent())->setButton(hotkeyButton); } } } } break; case EGET_EDITBOX_ENTER: switch (eventCallerId) { case ChatInputEditBox: IGUIElement* eb = Universe::instance->guienv->getRootGUIElement()->getElementFromId(ChatBox)->getElementFromId(ChatInputEditBox); if (wcslen(eb->getText()) > 0) { char outPacket[256]; CreatePacket(outPacket, Say, "%b%ws", Public, eb->getText()); Universe::instance->connectSocket->Send(outPacket); eb->setText(NULL); } break; } break; case EGDT_WINDOW_CLOSE: switch (eventCallerId) { case InventoryWindow: ((IGUIButton*)Universe::instance->guienv->getRootGUIElement()->getElementFromId(InventoryToggleButton))->setPressed(false); break; case SkillsWindow: ((IGUIButton*)Universe::instance->guienv->getRootGUIElement()->getElementFromId(SkillsToggleButton))->setPressed(false); break; } break; case EGET_BUTTON_CLICKED: switch (eventCallerId) { case IconTableItemButton: { char outPacket[256]; CreatePacket(outPacket, ItemUse, "%i", ((CGUIButton*)eventCaller)->currentGameObject->id); Universe::instance->connectSocket->Send(outPacket); break; } case IconTableSkillButton: { ((IGUIIconTable*)eventCaller->getParent()->getParent())->selectedButton = (CGUIButton*)eventCaller; //rightMouseBind = eventCaller; /* char outPacket[256]; CurrentMapObject<MapObject>* targetCurrentMapObject; int currentMapObjectId; int targetType; if (targetCurrentMapObject = (CurrentMapObject<MapObject>*)Universe::instance->render->GetCurrentMapObjectUnderCursor<CurrentNPC>(Universe::instance->currentLocation->currentNPCs, Universe::instance->currentLocation->currentNPCsCount)) { currentMapObjectId = targetCurrentMapObject->id; targetType = 0; } else if (targetCurrentMapObject = (CurrentMapObject<MapObject>*)Universe::instance->render->GetCurrentMapObjectUnderCursor<CurrentCharacter>(Universe::instance->currentLocation->currentCharacters, Universe::instance->currentLocation->currentCharactersCount)) { currentMapObjectId = targetCurrentMapObject->id; targetType = 3; } else { currentMapObjectId = 0; targetType = -1; } CreatePacket(outPacket, SkillUse, "%i%b%i", ((CGUIButton*)eventCaller)->currentGameObject->id, targetType, currentMapObjectId); Universe::instance->connectSocket->Send(outPacket); */ break; } case InventoryToggleButton: { IGUIWindow* wnd = (IGUIWindow*)Universe::instance->guienv->getRootGUIElement()->getElementFromId(InventoryWindow); if (wnd) wnd->remove(); else { int btnsSize = 48; wnd = Universe::instance->guienv->addWindow(rect< s32 >(Universe::instance->render->screenWidth - btnsSize * 6 - (6 - 1) * 2 - 20, 150, Universe::instance->render->screenWidth, 150 + 100 + btnsSize * 6 + (6 - 1) * 2 + 10), false, L"Inventory", NULL, InventoryWindow); IGUIIconTable* tbl = new IGUIIconTable(Universe::instance->guienv, wnd, InventoryItemsIconTable, rect< s32 >(10, 100, 10 + btnsSize * 6 + (6 - 1) * 2, 100 + btnsSize * 6 + (6 - 1) * 2), 6, 6); tbl->buttonSize = btnsSize; wnd->addChild(tbl); for (int i = 0; i < Universe::instance->currentCharacter->currentItemsCount; i++) { tbl->addButton((CurrentGameObject<GameObject>*)Universe::instance->currentCharacter->currentItems[i], IconTableItemButton); } } break; } case SkillsToggleButton: { IGUIWindow* wnd = (IGUIWindow*)Universe::instance->guienv->getRootGUIElement()->getElementFromId(SkillsWindow); if (wnd) wnd->remove(); else { int btnsSize = 48; wnd = Universe::instance->guienv->addWindow(rect< s32 >(Universe::instance->render->screenWidth - btnsSize * 6 - (6 - 1) * 2 - 20 - 400, 150, Universe::instance->render->screenWidth - 400, 150 + 100 + btnsSize * 6 + (6 - 1) * 2 + 10), false, L"Skills", NULL, SkillsWindow); IGUIIconTable* tbl = new IGUIIconTable(Universe::instance->guienv, wnd, SkillsIconTable, rect< s32 >(10, 100, 10 + btnsSize * 6 + (6 - 1) * 2, 100 + btnsSize * 6 + (6 - 1) * 2), 6, 6); tbl->buttonSize = btnsSize; wnd->addChild(tbl); for (int i = 0; i < Universe::instance->currentCharacter->currentSkillsCount; i++) { tbl->addButton((CurrentGameObject<GameObject>*)Universe::instance->currentCharacter->currentSkills[i], IconTableSkillButton); } } break; } case ChatInputEditBox: Universe::instance->guienv->getRootGUIElement()->getElementFromId(ChatInputEditBox)->setText(L""); break; default: if (eventCallerId > DialogElement) //Dialog button { char outPacket[256]; int currentNPCId; swscanf(eventCaller->getParent()->getText(), L"[%d]", ¤tNPCId); eventCaller->getParent()->remove(); CreatePacket(outPacket, DialogOpen, "%i%i", currentNPCId, eventCallerId - DialogElement); Universe::instance->connectSocket->Send(outPacket); } break; } break; case EGET_COMBO_BOX_CHANGED: break; case EGET_TAB_CHANGED: break; case EGET_CHECKBOX_CHANGED: break; } } return false; }