diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-06-15 22:25:12 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-06-15 22:25:12 -0300 |
| commit | 5bdedeecea69a5892e3ce8854e85f78537cf7ca4 (patch) | |
| tree | 8e3517fea9c641a5f2a10a4d5c98ddb479876f3a | |
| parent | 3cc587ab8df80d42d9dab1a73a37701f565a3499 (diff) | |
| download | game-5bdedeecea69a5892e3ce8854e85f78537cf7ca4.tar.gz game-5bdedeecea69a5892e3ce8854e85f78537cf7ca4.zip | |
channel functions
| -rw-r--r-- | reference/game.c | 807 | ||||
| -rw-r--r-- | src/containers.hh | 2 | ||||
| -rw-r--r-- | src/operate.cc | 391 | ||||
| -rw-r--r-- | src/operate.hh | 32 | ||||
| -rw-r--r-- | src/stubs.hh | 4 |
5 files changed, 427 insertions, 809 deletions
diff --git a/reference/game.c b/reference/game.c index 5fd4ee7..6b71785 100644 --- a/reference/game.c +++ b/reference/game.c @@ -18375,813 +18375,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return;
}
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-int GetNumberOfChannels(void)
-
-{
- return Channels;
-}
-
-
-
-bool ChannelActive(int ChannelID)
-
-{
- TChannel *pTVar1;
- bool bVar2;
-
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- error(&DAT_080ffea0,ChannelID);
- bVar2 = false;
- }
- else {
- bVar2 = true;
- if (7 < ChannelID) {
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar2 = pTVar1->Moderator != 0;
- }
- }
- return bVar2;
-}
-
-
-
-bool ChannelAvailable(int ChannelID,ulong CharacterID)
-
-{
- TPlayer *pl;
- TPlayer *pTVar1;
- TChannel *pTVar2;
- ulong *puVar3;
- int i;
- TChannel *C;
- bool bVar4;
- RIGHT Right;
-
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- error(&DAT_080ffea0,ChannelID);
- bVar4 = false;
- }
- else {
- bVar4 = true;
- if (7 < ChannelID) {
- pTVar2 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar4 = pTVar2->Moderator != 0;
- }
- }
- if (!bVar4) {
- return false;
- }
- pTVar1 = GetPlayer(CharacterID);
- if (pTVar1 == (TPlayer *)0x0) {
- error("ChannelAvailable: Spieler existiert nicht.\n");
- return false;
- }
- switch(ChannelID) {
- case 0:
- return pTVar1->Guild[0] != '\0';
- case 1:
- case 3:
- Right = READ_GAMEMASTER_CHANNEL;
- break;
- case 2:
- Right = READ_TUTOR_CHANNEL;
- break;
- case 4:
- case 5:
- case 6:
- case 7:
- return true;
- default:
- if (ChannelID < 8) {
- return false;
- }
- pTVar2 = vector<TChannel>::operator()(&Channel,ChannelID);
- if (CharacterID == pTVar2->Moderator) {
- return true;
- }
- i = 0;
- if (pTVar2->InvitedPlayers < 1) {
- return false;
- }
- do {
- puVar3 = vector<>::operator()(&pTVar2->InvitedPlayer,i);
- if (CharacterID == *puVar3) {
- return true;
- }
- i = i + 1;
- } while (i < pTVar2->InvitedPlayers);
- return false;
- }
- bVar4 = CheckRight(CharacterID,Right);
- return bVar4;
-}
-
-
-
-char * GetChannelName(int ChannelID,ulong CharacterID)
-
-{
- TPlayer *pTVar1;
- TChannel *pTVar2;
- char *pcVar3;
- bool bVar4;
-
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- error(&DAT_080ffea0,ChannelID);
- bVar4 = false;
- }
- else {
- bVar4 = true;
- if (7 < ChannelID) {
- pTVar2 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar4 = pTVar2->Moderator != 0;
- }
- }
- if (!bVar4) {
- return "Unknown";
- }
- pTVar1 = GetPlayer(CharacterID);
- if (pTVar1 == (TPlayer *)0x0) {
- error("GetChannelName: Spieler existiert nicht.\n");
-LAB_080999fd:
- pcVar3 = "Unknown";
- }
- else {
- switch(ChannelID) {
- case 0:
- pcVar3 = pTVar1->Guild;
- break;
- case 1:
- pcVar3 = "Gamemaster";
- break;
- case 2:
- pcVar3 = "Tutor";
- break;
- case 3:
- pcVar3 = "Rule Violations";
- break;
- case 4:
- pcVar3 = "Game-Chat";
- break;
- case 5:
- pcVar3 = "Trade";
- break;
- case 6:
- pcVar3 = "RL-Chat";
- break;
- case 7:
- pcVar3 = "Help";
- break;
- default:
- if (7 < ChannelID) {
- pTVar2 = vector<TChannel>::operator()(&Channel,ChannelID);
- sprintf(GetChannelName::ChannelName,"%s\'s Channel",pTVar2->ModeratorName);
- return GetChannelName::ChannelName;
- }
- error("GetChannelName: Unbenutzter Kanal %d.\n",ChannelID);
- goto LAB_080999fd;
- }
- }
- return pcVar3;
-}
-
-
-
-bool ChannelSubscribed(int ChannelID,ulong CharacterID)
-
-{
- TChannel *pTVar1;
- ulong *puVar2;
- int i;
- TChannel *C;
- bool bVar3;
-
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- error(&DAT_080ffea0,ChannelID);
- bVar3 = false;
- }
- else {
- bVar3 = true;
- if (7 < ChannelID) {
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar3 = pTVar1->Moderator != 0;
- }
- }
- if (bVar3) {
- i = 0;
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- if (0 < pTVar1->Subscribers) {
- do {
- puVar2 = vector<>::operator()(&pTVar1->Subscriber,i);
- if (CharacterID == *puVar2) {
- return true;
- }
- i = i + 1;
- } while (i < pTVar1->Subscribers);
- }
- }
- return false;
-}
-
-
-
-ulong GetFirstSubscriber(int ChannelID)
-
-{
- int i;
- TChannel *pTVar1;
- ulong *puVar2;
- TChannel *C;
- ulong uVar3;
- bool bVar4;
-
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- error(&DAT_080ffea0,ChannelID);
- bVar4 = false;
- }
- else {
- bVar4 = true;
- if (7 < ChannelID) {
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar4 = pTVar1->Moderator != 0;
- }
- }
- uVar3 = 0;
- if (bVar4) {
- CurrentChannelID = ChannelID;
- CurrentSubscriberNumber = 0;
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- error(&DAT_080ffea0,ChannelID);
- bVar4 = false;
- }
- else {
- bVar4 = true;
- if (7 < ChannelID) {
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar4 = pTVar1->Moderator != 0;
- }
- }
- uVar3 = 0;
- if (bVar4) {
- pTVar1 = vector<TChannel>::operator()(&Channel,CurrentChannelID);
- i = CurrentSubscriberNumber;
- if (CurrentSubscriberNumber < pTVar1->Subscribers) {
- CurrentSubscriberNumber = CurrentSubscriberNumber + 1;
- puVar2 = vector<>::operator()(&pTVar1->Subscriber,i);
- uVar3 = *puVar2;
- }
- else {
- uVar3 = 0;
- }
- }
- }
- return uVar3;
-}
-
-
-
-// WARNING: Unknown calling convention -- yet parameter storage is locked
-
-ulong GetNextSubscriber(void)
-
-{
- int i;
- TChannel *pTVar1;
- ulong *puVar2;
- TChannel *C;
- ulong uVar3;
- bool bVar4;
-
- if ((CurrentChannelID < 0) || (Channels <= CurrentChannelID)) {
- error(&DAT_080ffea0,CurrentChannelID);
- bVar4 = false;
- }
- else {
- bVar4 = true;
- if (7 < CurrentChannelID) {
- pTVar1 = vector<TChannel>::operator()(&Channel,CurrentChannelID);
- bVar4 = pTVar1->Moderator != 0;
- }
- }
- uVar3 = 0;
- if (bVar4) {
- pTVar1 = vector<TChannel>::operator()(&Channel,CurrentChannelID);
- i = CurrentSubscriberNumber;
- if (CurrentSubscriberNumber < pTVar1->Subscribers) {
- CurrentSubscriberNumber = CurrentSubscriberNumber + 1;
- puVar2 = vector<>::operator()(&pTVar1->Subscriber,i);
- uVar3 = *puVar2;
- }
- else {
- uVar3 = 0;
- }
- }
- return uVar3;
-}
-
-
-
-bool MayOpenChannel(ulong CharacterID)
-
-{
- bool bVar1;
- TChannel *pTVar2;
- bool bVar3;
- int i;
- int i_00;
-
- if (Channels < 0xffff) {
- bVar1 = CheckRight(CharacterID,PREMIUM_ACCOUNT);
- bVar3 = false;
- if (bVar1) {
- i_00 = 8;
- if (8 < Channels) {
- do {
- pTVar2 = vector<TChannel>::operator()(&Channel,i_00);
- if (pTVar2->Moderator == CharacterID) goto LAB_08099cfb;
- i_00 = i_00 + 1;
- } while (i_00 < Channels);
- }
- bVar3 = true;
- }
- }
- else {
-LAB_08099cfb:
- bVar3 = false;
- }
- return bVar3;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: pl
-
-void OpenChannel(ulong CharacterID)
-
-{
- bool bVar1;
- TPlayer *pTVar2;
- TChannel *pTVar3;
- ulong *puVar4;
- undefined4 *puVar5;
- int ChannelID;
- int i;
- TChannel *C;
- int i_00;
- TPlayer *pl;
-
- // try { // try from 08099d75 to 08099ef2 has its CatchHandler @ 08099ef5
- pTVar2 = GetPlayer(CharacterID);
- if (pTVar2 == (TPlayer *)0x0) {
- error("OpenChannel: Kreatur %lu existiert nicht.\n",CharacterID);
- }
- else {
- if (Channels < 0xffff) {
- bVar1 = CheckRight(CharacterID,PREMIUM_ACCOUNT);
- if (bVar1) {
- i = 8;
- if (8 < Channels) {
- do {
- pTVar3 = vector<TChannel>::operator()(&Channel,i);
- if (pTVar3->Moderator == CharacterID) goto LAB_08099e20;
- i = i + 1;
- } while (i < Channels);
- }
- i_00 = 8;
- i = Channels;
- if (8 < Channels) {
- do {
- pTVar3 = vector<TChannel>::operator()(&Channel,i_00);
- if (pTVar3->Moderator == 0) {
- i = i_00;
- }
- i_00 = i_00 + 1;
- } while (i_00 < Channels);
- }
- if (i == Channels) {
- Channels = i + 1;
- }
- pTVar3 = vector<TChannel>::operator()(&Channel,i);
- pTVar3->Moderator = CharacterID;
- strcpy(pTVar3->ModeratorName,(pTVar2->super_TCreature).Name);
- puVar4 = vector<>::operator()(&pTVar3->Subscriber,0);
- *puVar4 = CharacterID;
- pTVar3->Subscribers = 1;
- pTVar3->InvitedPlayers = 0;
-LAB_08099e20:
- SendOpenOwnChannel((pTVar2->super_TCreature).Connection,i);
- return;
- }
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0x33;
- goto LAB_08099eab;
- }
- error(&DAT_081009a0);
- }
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0xffffffff;
-LAB_08099eab:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar5,&RESULT::typeinfo,0);
-}
-
-
-
-void CloseChannel(int ChannelID)
-
-{
- TChannel *pTVar1;
-
- if ((ChannelID < 8) || (Channels <= ChannelID)) {
- error(&DAT_08100a00,ChannelID);
- }
- else {
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- if (pTVar1->Moderator == 0) {
- error("CloseChannel: Kanal ist schon geschlossen.\n");
- return;
- }
- pTVar1->Moderator = 0;
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Opp
-
-void InviteToChannel(ulong CharacterID,char *Name)
-
-{
- bool bVar1;
- TPlayer *pTVar2;
- int iVar3;
- ulong *puVar4;
- undefined4 *puVar5;
- TChannel *pTVar6;
- char *pcVar7;
- ulong OppID;
- TChannel *pTVar8;
- ulong uVar9;
- TPlayer *pl;
- int local_20;
- int i_1;
- TChannel *C;
- int channel;
- TPlayer *Opp;
-
- // try { // try from 08099f85 to 0809a218 has its CatchHandler @ 0809a220
- pTVar2 = GetPlayer(CharacterID);
- if (pTVar2 == (TPlayer *)0x0) {
- error("InviteToChannel: Kreatur %lu existiert nicht.\n",CharacterID);
- return;
- }
- C = (TChannel *)0xffffffff;
- pTVar8 = (TChannel *)0x8;
- if (8 < Channels) {
- do {
- pTVar6 = vector<TChannel>::operator()(&Channel,(int)pTVar8);
- if (pTVar6->Moderator == CharacterID) {
- C = pTVar8;
- }
- pTVar8 = (TChannel *)((int)&pTVar8->Moderator + 1);
- } while ((int)pTVar8 < Channels);
- }
- if (C == (TChannel *)0xffffffff) {
- return;
- }
- uVar9 = 0;
- channel = 0;
- bVar1 = CheckRight((pTVar2->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- iVar3 = IdentifyPlayer(Name,false,!bVar1,(TPlayer **)&channel);
- if (iVar3 == -1) {
- uVar9 = GetCharacterID(Name);
- if (uVar9 == 0) {
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0x1a;
-LAB_0809a19d:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar5,&RESULT::typeinfo,0);
- }
- }
- else {
- if (-1 < iVar3) {
- if (iVar3 == 0) {
- uVar9 = *(ulong *)(channel + 0x208);
- Name = (char *)(channel + 0x214);
- }
- goto LAB_0809a01f;
- }
- if (iVar3 != -2) goto LAB_0809a01f;
- uVar9 = GetCharacterID(Name);
- if (uVar9 == 0) {
- puVar5 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar5 = 0x1c;
- goto LAB_0809a19d;
- }
- }
- Name = GetCharacterName(Name);
-LAB_0809a01f:
- print();
- pTVar8 = vector<TChannel>::operator()(&Channel,(int)C);
- if (CharacterID != uVar9) {
- local_20 = 0;
- iVar3 = pTVar8->InvitedPlayers;
- if (0 < iVar3) {
- do {
- puVar4 = vector<>::operator()(&pTVar8->InvitedPlayer,local_20);
- if (*puVar4 == uVar9) {
- SendMessage((pTVar2->super_TCreature).Connection,0x16,
- "%s has already been invited.",Name);
- return;
- }
- local_20 = local_20 + 1;
- iVar3 = pTVar8->InvitedPlayers;
- } while (local_20 < iVar3);
- }
- puVar4 = vector<>::operator()(&pTVar8->InvitedPlayer,iVar3);
- *puVar4 = uVar9;
- pTVar8->InvitedPlayers = pTVar8->InvitedPlayers + 1;
- SendMessage((pTVar2->super_TCreature).Connection,0x16,"%s has been invited.",Name);
- if (channel != 0) {
- pcVar7 = "his";
- if ((pTVar2->super_TCreature).Sex != 1) {
- pcVar7 = "her";
- }
- SendMessage(*(TConnection **)(channel + 0x318),0x16,
- "%s invites you to %s private chat channel.",(pTVar2->super_TCreature).Name,
- pcVar7);
- }
- }
- return;
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: Opp
-
-void ExcludeFromChannel(ulong CharacterID,char *Name)
-
-{
- bool bVar1;
- TPlayer *pTVar2;
- int iVar3;
- ulong *puVar4;
- ulong *puVar5;
- undefined4 *puVar6;
- TChannel *pTVar7;
- ulong OppID;
- TChannel *pTVar8;
- ulong CharacterID_00;
- int i;
- int local_24;
- int Position;
- TChannel *C;
- int channel;
- TPlayer *pl;
- TPlayer *Opp;
-
- // try { // try from 0809a258 to 0809a4fe has its CatchHandler @ 0809a504
- pTVar2 = GetPlayer(CharacterID);
- if (pTVar2 == (TPlayer *)0x0) {
- error("ExcludeFromChannel: Kreatur %lu existiert nicht.\n",CharacterID);
- }
- else {
- C = (TChannel *)0xffffffff;
- pTVar8 = (TChannel *)0x8;
- if (8 < Channels) {
- do {
- pTVar7 = vector<TChannel>::operator()(&Channel,(int)pTVar8);
- if (pTVar7->Moderator == CharacterID) {
- C = pTVar8;
- }
- pTVar8 = (TChannel *)((int)&pTVar8->Moderator + 1);
- } while ((int)pTVar8 < Channels);
- }
- if (C != (TChannel *)0xffffffff) {
- CharacterID_00 = 0;
- pl = (TPlayer *)0x0;
- bVar1 = CheckRight((pTVar2->super_TCreature).ID,READ_GAMEMASTER_CHANNEL);
- iVar3 = IdentifyPlayer(Name,false,!bVar1,&pl);
- if (iVar3 == -1) {
- CharacterID_00 = GetCharacterID(Name);
- if (CharacterID_00 == 0) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0x1a;
-LAB_0809a484:
- // WARNING: Subroutine does not return
- __cxa_throw(puVar6,&RESULT::typeinfo,0);
- }
- }
- else if (iVar3 < 0) {
- if ((iVar3 == -2) && (CharacterID_00 = GetCharacterID(Name), CharacterID_00 == 0)) {
- puVar6 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar6 = 0x1c;
- goto LAB_0809a484;
- }
- }
- else if (iVar3 == 0) {
- CharacterID_00 = (pl->super_TCreature).ID;
- Name = (pl->super_TCreature).Name;
- }
- print();
- pTVar8 = vector<TChannel>::operator()(&Channel,(int)C);
- if (CharacterID != CharacterID_00) {
- local_24 = -1;
- iVar3 = pTVar8->InvitedPlayers;
- i = 0;
- if (0 < iVar3) {
- do {
- puVar4 = vector<>::operator()(&pTVar8->InvitedPlayer,i);
- if (*puVar4 == CharacterID_00) {
- local_24 = i;
- }
- i = i + 1;
- iVar3 = pTVar8->InvitedPlayers;
- } while (i < iVar3);
- }
- if (local_24 == -1) {
- SendMessage((pTVar2->super_TCreature).Connection,0x16,"%s has not been invited."
- ,Name);
- }
- else {
- pTVar8->InvitedPlayers = iVar3 + -1;
- puVar4 = vector<>::operator()(&pTVar8->InvitedPlayer,local_24);
- puVar5 = vector<>::operator()(&pTVar8->InvitedPlayer,pTVar8->InvitedPlayers);
- *puVar4 = *puVar5;
- SendMessage((pTVar2->super_TCreature).Connection,0x16,"%s has been excluded.",
- Name);
- bVar1 = ChannelSubscribed((int)C,CharacterID_00);
- if (bVar1) {
- LeaveChannel((int)C,CharacterID_00,false);
- SendCloseChannel((pl->super_TCreature).Connection,(int)C);
- }
- }
- }
- }
- }
- return;
-}
-
-
-
-bool JoinChannel(int ChannelID,ulong CharacterID)
-
-{
- bool bVar1;
- TChannel *pTVar2;
- ulong *puVar3;
- undefined4 *puVar4;
- TChannel *C;
-
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- // try { // try from 0809a550 to 0809a61d has its CatchHandler @ 0809a630
- error(&DAT_080ffea0,ChannelID);
- bVar1 = false;
- }
- else {
- bVar1 = true;
- if (7 < ChannelID) {
- pTVar2 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar1 = pTVar2->Moderator != 0;
- }
- }
- if (bVar1) {
- bVar1 = ChannelAvailable(ChannelID,CharacterID);
- if (bVar1) {
- pTVar2 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar1 = ChannelSubscribed(ChannelID,CharacterID);
- if (!bVar1) {
- puVar3 = vector<>::operator()(&pTVar2->Subscriber,pTVar2->Subscribers);
- *puVar3 = CharacterID;
- pTVar2->Subscribers = pTVar2->Subscribers + 1;
- }
- return CharacterID == pTVar2->Moderator;
- }
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 1;
- }
- else {
- puVar4 = (undefined4 *)__cxa_allocate_exception(4);
- *puVar4 = 0xffffffff;
- }
- // WARNING: Subroutine does not return
- __cxa_throw(puVar4,&RESULT::typeinfo,0);
-}
-
-
-
-// WARNING: Variable defined which should be unmapped: CharacterID_local
-
-void LeaveChannel(int ChannelID,ulong CharacterID,bool Close)
-
-{
- vector<> *this;
- TChannel *C_1;
- TChannel *pTVar1;
- ulong *puVar2;
- TPlayer *pTVar3;
- ulong *puVar4;
- int i;
- int iVar5;
- TChannel *C;
- bool bVar6;
- bool Close_local;
- ulong CharacterID_local;
-
- if ((ChannelID < 0) || (Channels <= ChannelID)) {
- error(&DAT_080ffea0,ChannelID);
- bVar6 = false;
- }
- else {
- bVar6 = true;
- if (7 < ChannelID) {
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- bVar6 = pTVar1->Moderator != 0;
- }
- }
- if (bVar6) {
- iVar5 = 0;
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- if (0 < pTVar1->Subscribers) {
- this = &pTVar1->Subscriber;
- do {
- puVar2 = vector<>::operator()(this,iVar5);
- if (CharacterID == *puVar2) {
- pTVar1->Subscribers = pTVar1->Subscribers + -1;
- puVar2 = vector<>::operator()(this,iVar5);
- puVar4 = vector<>::operator()(this,pTVar1->Subscribers);
- *puVar2 = *puVar4;
- break;
- }
- iVar5 = iVar5 + 1;
- } while (iVar5 < pTVar1->Subscribers);
- }
- if ((Close) && (CharacterID == pTVar1->Moderator)) {
- iVar5 = 0;
- if (0 < pTVar1->Subscribers) {
- do {
- puVar2 = vector<>::operator()(&pTVar1->Subscriber,iVar5);
- pTVar3 = GetPlayer(*puVar2);
- if (pTVar3 != (TPlayer *)0x0) {
- SendCloseChannel((pTVar3->super_TCreature).Connection,ChannelID);
- }
- iVar5 = iVar5 + 1;
- } while (iVar5 < pTVar1->Subscribers);
- }
- pTVar1->Subscribers = 0;
- }
- if ((7 < ChannelID) && (pTVar1->Subscribers == 0)) {
- if (Channels <= ChannelID) {
- error(&DAT_08100a00);
- return;
- }
- pTVar1 = vector<TChannel>::operator()(&Channel,ChannelID);
- if (pTVar1->Moderator == 0) {
- error("CloseChannel: Kanal ist schon geschlossen.\n");
- return;
- }
- pTVar1->Moderator = 0;
- }
- }
- return;
-}
-
-
-
-void LeaveAllChannels(ulong CharacterID)
-
-{
- TChannel *pTVar1;
- int ChannelID;
- int i;
- bool bVar2;
-
- i = 0;
- if (0 < Channels) {
- do {
- if ((i < 0) || (Channels <= i)) {
- error(&DAT_080ffea0,i);
- bVar2 = false;
- }
- else {
- bVar2 = true;
- if (7 < i) {
- pTVar1 = vector<TChannel>::operator()(&Channel,i);
- bVar2 = pTVar1->Moderator != 0;
- }
- }
- if (bVar2) {
- LeaveChannel(i,CharacterID,false);
- }
- i = i + 1;
- } while (i < Channels);
- }
- return;
-}
-
TParty * GetParty(ulong Leader)
{
diff --git a/src/containers.hh b/src/containers.hh index f82159b..ecbe6be 100644 --- a/src/containers.hh +++ b/src/containers.hh @@ -122,6 +122,8 @@ struct vector{ T Result = {}; if(index >= this->start && index < (this->start + this->space)){ Result = this->entry[index - this->start]; + }else if(this->initialized){ + Result = this->init; } return Result; } diff --git a/src/operate.cc b/src/operate.cc index 2224ed4..7d18a94 100644 --- a/src/operate.cc +++ b/src/operate.cc @@ -3387,6 +3387,10 @@ void TChannel::operator=(const TChannel &Other){ } } +int GetNumberOfChannels(void){ + return Channels; +} + bool ChannelActive(int ChannelID){ if(ChannelID < 0 || ChannelID >= Channels){ error("ChannelActive: Ungültige Kanalnummer %d.\n", ChannelID); @@ -3396,6 +3400,44 @@ bool ChannelActive(int ChannelID){ return ChannelID <= 7 || Channel.at(ChannelID)->Moderator != 0; } +bool ChannelAvailable(int ChannelID, uint32 CharacterID){ + if(!ChannelActive(ChannelID)){ + return false; + } + + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL){ + error("ChannelAvailable: Spieler existiert nicht.\n"); + return false; + } + + switch(ChannelID){ + case 0: return Player->Guild[0] != 0; + case 1: return CheckRight(Player->ID, READ_GAMEMASTER_CHANNEL); + case 2: return CheckRight(Player->ID, READ_TUTOR_CHANNEL); + case 3: return CheckRight(Player->ID, READ_GAMEMASTER_CHANNEL); + case 4: return true; + case 5: return true; + case 6: return true; + case 7: return true; + default:{ + if(ChannelID > 7){ + TChannel *Chan = Channel.at(ChannelID); + if(Chan->Moderator == CharacterID){ + return true; + } + + for(int i = 0; i < Chan->InvitedPlayers; i += 1){ + if(*Chan->InvitedPlayer.at(i) == CharacterID){ + return true; + } + } + } + return false; + } + } +} + const char *GetChannelName(int ChannelID, uint32 CharacterID){ static char ChannelName[40]; @@ -3410,7 +3452,7 @@ const char *GetChannelName(int ChannelID, uint32 CharacterID){ } switch(ChannelID){ - case 0: return Player->Guild; + case 0: return Player->Guild; case 1: return "Gamemaster"; case 2: return "Tutor"; case 3: return "Rule Violations"; @@ -3431,6 +3473,353 @@ const char *GetChannelName(int ChannelID, uint32 CharacterID){ } } +bool ChannelSubscribed(int ChannelID, uint32 CharacterID){ + if(!ChannelActive(ChannelID)){ + return false; + } + + TChannel *Chan = Channel.at(ChannelID); + for(int i = 0; i < Chan->Subscribers; i += 1){ + if(*Chan->Subscriber.at(i) == CharacterID){ + return true; + } + } + + return false; +} + +// TODO(fusion): This could have been a simple for loop? +uint32 GetFirstSubscriber(int ChannelID){ + CurrentChannelID = ChannelID; + CurrentSubscriberNumber = 0; + return GetNextSubscriber(); +} + +uint32 GetNextSubscriber(void){ + if(!ChannelActive(CurrentChannelID)){ + return 0; + } + + uint32 Subscriber = 0; + TChannel *Chan = Channel.at(CurrentChannelID); + if(CurrentSubscriberNumber < Chan->Subscribers){ + Subscriber = *Chan->Subscriber.at(CurrentSubscriberNumber); + CurrentSubscriberNumber += 1; + } + + return Subscriber; +} + +bool MayOpenChannel(uint32 CharacterID){ + if(Channels >= 0xFFFF){ + return false; + } + + if(!CheckRight(CharacterID, PREMIUM_ACCOUNT)){ + return false; + } + + // NOTE(fusion): Check if character is already moderator of any non-public channel. + for(int ChannelID = 8; ChannelID < Channels; ChannelID += 1){ + if(Channel.at(ChannelID)->Moderator == CharacterID){ + return false; + } + } + + return true; +} + +void OpenChannel(uint32 CharacterID){ + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL){ + error("OpenChannel: Kreatur %u existiert nicht.\n", CharacterID); + throw ERROR; + } + + // TODO(fusion): Shouldn't we scan for a free channel before returning here? + if(Channels >= 0xFFFF){ + error("OpenChannel: Zu viele Kanäle.\n"); + throw ERROR; + } + + if(!CheckRight(CharacterID, PREMIUM_ACCOUNT)){ + throw NOPREMIUMACCOUNT; + } + + // NOTE(fusion): Check if character already has an open channel. + for(int ChannelID = 8; ChannelID < Channels; ChannelID += 1){ + if(Channel.at(ChannelID)->Moderator == CharacterID){ + SendOpenOwnChannel(Player->Connection, ChannelID); + return; + } + } + + // NOTE(fusion): Assign free channel to character. + int ChannelID = 8; + while(ChannelID < Channels){ + if(Channel.at(ChannelID)->Moderator == 0){ + break; + } + ChannelID += 1; + } + + if(ChannelID == Channels){ + Channels += 1; + } + + TChannel *Chan = Channel.at(ChannelID); + Chan->Moderator = CharacterID; + strcpy(Chan->ModeratorName, Player->Name); + *Chan->Subscriber.at(0) = CharacterID; + Chan->Subscribers = 1; + Chan->InvitedPlayers = 0; + SendOpenOwnChannel(Player->Connection, ChannelID); +} + +void CloseChannel(int ChannelID){ + if(ChannelID <= 7 || ChannelID >= Channels){ + error("CloseChannel: Ungültige ChannelID %d.\n", ChannelID); + return; + } + + TChannel *Chan = Channel.at(ChannelID); + if(Chan->Moderator == 0){ + error("CloseChannel: Kanal ist schon geschlossen.\n"); + return; + } + + Chan->Moderator = 0; +} + +void InviteToChannel(uint32 CharacterID, const char *Name){ + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL){ + error("InviteToChannel: Kreatur %u existiert nicht.\n", CharacterID); + return; + } + + int ChannelID = 8; + while(ChannelID < Channels){ + if(Channel.at(ChannelID)->Moderator == CharacterID){ + break; + } + ChannelID += 1; + } + + if(ChannelID >= Channels){ + return; + } + + TPlayer *Other = NULL; + uint32 OtherID = 0; + bool IgnoreGamemasters = !CheckRight(Player->ID, READ_GAMEMASTER_CHANNEL); + switch(IdentifyPlayer(Name, false, IgnoreGamemasters, &Other)){ + case 0:{ // PLAYERFOUND ? + OtherID = Other->ID; + Name = Other->Name; + break; + } + + case -1:{ // PLAYERNOTONLINE ? + OtherID = GetCharacterID(Name); + if(OtherID == 0){ + throw PLAYERNOTEXISTING; + } + + Name = GetCharacterName(Name); + break; + } + + case -2:{ // NAMEAMBIGUOUS ? + OtherID = GetCharacterID(Name); + if(OtherID == 0){ + throw NAMEAMBIGUOUS; + } + + Name = GetCharacterName(Name); + break; + } + + default:{ + // TODO(fusion): This wasn't here but I don't think `IdentifyPlayer` + // can return anything else than 0, -1, and -2 anyways. + error("InviteToChannel: Ungültiger Rückgabewert von IdentifyPlayer.\n"); + throw ERROR; + } + } + + print(3, "Lade Spieler %s (%u) in Private Channel ein.\n", Name, OtherID); + if(CharacterID != OtherID){ + TChannel *Chan = Channel.at(ChannelID); + for(int i = 0; i < Chan->InvitedPlayers; i += 1){ + if(*Chan->InvitedPlayer.at(i) == OtherID){ + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "%s has already been invited.", Name); + return; + } + } + + *Chan->InvitedPlayer.at(Chan->InvitedPlayers) = OtherID; + Chan->InvitedPlayers += 1; + + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "%s has been invited.", Name); + + if(Other != NULL){ + SendMessage(Other->Connection, TALK_INFO_MESSAGE, + "%s invites you to %s private chat channel.", + Player->Name, (Player->Sex == 1 ? "his" : "her")); + } + } +} + +void ExcludeFromChannel(uint32 CharacterID, const char *Name){ + TPlayer *Player = GetPlayer(CharacterID); + if(Player == NULL){ + error("ExcludeFromChannel: Kreatur %u existiert nicht.\n", CharacterID); + return; + } + + int ChannelID = 8; + while(ChannelID < Channels){ + if(Channel.at(ChannelID)->Moderator == CharacterID){ + break; + } + ChannelID += 1; + } + + if(ChannelID >= Channels){ + return; + } + + // TODO(fusion): Why don't we call `GetCharacterName` as we do in + // `InviteToChannel`, when the player is not found? + TPlayer *Other = NULL; + uint32 OtherID = 0; + bool IgnoreGamemasters = !CheckRight(Player->ID, READ_GAMEMASTER_CHANNEL); + switch(IdentifyPlayer(Name, false, IgnoreGamemasters, &Other)){ + case 0:{ // PLAYERFOUND ? + OtherID = Other->ID; + Name = Other->Name; + break; + } + + case -1:{ // PLAYERNOTONLINE ? + OtherID = GetCharacterID(Name); + if(OtherID == 0){ + throw PLAYERNOTEXISTING; + } + break; + } + + case -2:{ // NAMEAMBIGUOUS ? + OtherID = GetCharacterID(Name); + if(OtherID == 0){ + throw NAMEAMBIGUOUS; + } + break; + } + + default:{ + // TODO(fusion): Same as `InviteToChannel`. + error("ExcludeFromChannel: Ungültiger Rückgabewert von IdentifyPlayer.\n"); + throw ERROR; + } + } + + print(3, "Schließe Spieler %s (%u) aus Private Channel aus.\n", Name, OtherID); + if(CharacterID != OtherID){ + bool Removed = false; + TChannel *Chan = Channel.at(ChannelID); + for(int i = 0; i < Chan->InvitedPlayers; i += 1){ + if(*Chan->InvitedPlayer.at(i) == OtherID){ + // NOTE(fusion): A little swap and pop action. + Chan->InvitedPlayers -= 1; + *Chan->InvitedPlayer.at(i) = *Chan->InvitedPlayer.at(Chan->InvitedPlayers); + Removed = true; + break; + } + } + + if(!Removed){ + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "%s has not been invited.", Name); + }else{ + SendMessage(Player->Connection, TALK_INFO_MESSAGE, + "%s has been excluded.", Name); + if(ChannelSubscribed(ChannelID, OtherID)){ + LeaveChannel(ChannelID, OtherID, false); + + // TODO(fusion): We didn't check if `Other` was NULL here. It + // seems that the player destructor will call `LeaveAllChannels` + // to make sure a player is only subscribed if it is still valid. + // Nevertheless, this check should become invisible to the branch + // predictor and it's always best to be safe. + if(Other != NULL){ + SendCloseChannel(Other->Connection, ChannelID); + } + } + } + } +} + +bool JoinChannel(int ChannelID, uint32 CharacterID){ + if(!ChannelActive(ChannelID)){ + throw ERROR; + } + + if(!ChannelAvailable(ChannelID, CharacterID)){ + throw NOTACCESSIBLE; + } + + TChannel *Chan = Channel.at(ChannelID); + if(!ChannelSubscribed(ChannelID, CharacterID)){ + *Chan->Subscriber.at(Chan->Subscribers) = CharacterID; + Chan->Subscribers += 1; + } + + return CharacterID == Chan->Moderator; +} + +void LeaveChannel(int ChannelID, uint32 CharacterID, bool Close){ + if(!ChannelActive(ChannelID)){ + return; + } + + TChannel *Chan = Channel.at(ChannelID); + for(int i = 0; i < Chan->Subscribers; i += 1){ + if(*Chan->Subscriber.at(i) == CharacterID){ + // NOTE(fusion): A little swap and pop action. + Chan->Subscribers -= 1; + *Chan->Subscriber.at(i) = *Chan->Subscriber.at(Chan->Subscribers); + break; + } + } + + if(Close && CharacterID == Chan->Moderator){ + for(int i = 0; i < Chan->Subscribers; i += 1){ + uint32 SubscriberID = *Chan->Subscriber.at(i); + TPlayer *Subscriber = GetPlayer(SubscriberID); + if(Subscriber != NULL){ + SendCloseChannel(Subscriber->Connection, ChannelID); + } + } + Chan->Subscribers = 0; + } + + if(ChannelID > 7 && Chan->Subscribers == 0){ + CloseChannel(ChannelID); + } +} + +void LeaveAllChannels(uint32 CharacterID){ + for(int ChannelID = 0; ChannelID < Channels; ChannelID += 1){ + if(ChannelActive(ChannelID)){ + LeaveChannel(ChannelID, CharacterID, false); + } + } +} + // Party // ============================================================================= TParty::TParty(void) : Member(0, 10, 10), InvitedPlayer(0, 10, 10) { diff --git a/src/operate.hh b/src/operate.hh index 0c370a2..4942569 100644 --- a/src/operate.hh +++ b/src/operate.hh @@ -22,6 +22,23 @@ enum : int { OBJECT_MOVED = 3, }; +// TODO(fusion): Use these? +enum : int { + CHANNEL_GUILD = 0, + CHANNEL_GAMEMASTER = 1, + CHANNEL_TUTOR = 2, + CHANNEL_RULEVIOLATIONS = 3, + CHANNEL_GAMECHAT = 4, + CHANNEL_TRADE = 5, + CHANNEL_RLCHAT = 6, + CHANNEL_HELP = 7, + + CHANNEL_PUBLIC_FIRST = 0, + CHANNEL_PUBLIC_LAST = 7, + CHANNEL_PRIVATE_FIRST = 8, + CHANNEL_PRIVATE_LAST = 0xFFFF, +}; + struct TChannel { TChannel(void); @@ -155,7 +172,20 @@ void ProcessCommunicationControl(void); int GetCommunicationContext(uint32 CharacterID, uint32 StatementID, int *NumberOfStatements, vector<TReportedStatement> **ReportedStatements); -uint32 GetFirstSubscriber(int Channel); +int GetNumberOfChannels(void); +bool ChannelActive(int ChannelID); +bool ChannelAvailable(int ChannelID, uint32 CharacterID); +const char *GetChannelName(int ChannelID, uint32 CharacterID); +bool ChannelSubscribed(int ChannelID, uint32 CharacterID); +uint32 GetFirstSubscriber(int ChannelID); uint32 GetNextSubscriber(void); +bool MayOpenChannel(uint32 CharacterID); +void OpenChannel(uint32 CharacterID); +void CloseChannel(int ChannelID); +void InviteToChannel(uint32 CharacterID, const char *Name); +void ExcludeFromChannel(uint32 CharacterID, const char *Name); +bool JoinChannel(int ChannelID, uint32 CharacterID); +void LeaveChannel(int ChannelID, uint32 CharacterID, bool Close); +void LeaveAllChannels(uint32 CharacterID); #endif //TIBIA_OPERATE_HH_ diff --git a/src/stubs.hh b/src/stubs.hh index df270ff..bb68d1d 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -24,6 +24,8 @@ extern void ConvinceMonster(TCreature *Master, TCreature *Slave); extern void ChallengeMonster(TCreature *Challenger, TCreature *Monster); extern TCreature *CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect); extern void CreatePlayerList(bool Online); +extern uint32 GetCharacterID(const char *Name); +extern const char *GetCharacterName(const char *Name); extern void GetExitPosition(uint16 HouseID, int *x, int *y, int *z); extern TConnection *GetFirstConnection(void); extern TConnection *GetNextConnection(void); @@ -53,6 +55,7 @@ extern void SendAll(void); extern void SendAmbiente(TConnection *Connection); extern void SendClearTarget(TConnection *Connection); extern void SendContainer(TConnection *Connection, int ContainerNr); +extern void SendCloseChannel(TConnection *Connection, int ChannelID); extern void SendCloseContainer(TConnection *Connection, int ContainerNr); extern void SendCloseTrade(TConnection *Connection); extern void SendCreatureHealth(TConnection *Connection, uint32 CreatureID); @@ -80,6 +83,7 @@ extern void SendMails(TPlayerData *PlayerData); extern void SendMarkCreature(TConnection *Connection, uint32 CreatureID, int Color); extern void SendMessage(TConnection *Connection, int Mode, const char *Text, ...) ATTR_PRINTF(3, 4); extern void SendMoveCreature(TConnection *Connection, uint32 CreatureID, int x, int y, int z); +extern void SendOpenOwnChannel(TConnection *Connection, int Channel); extern void SendPlayerData(TConnection *Connection); extern void SendPlayerSkills(TConnection *Connection); extern void SendPlayerState(TConnection *Connection, uint8 State); |
