aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-15 22:25:12 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-15 22:25:12 -0300
commit5bdedeecea69a5892e3ce8854e85f78537cf7ca4 (patch)
tree8e3517fea9c641a5f2a10a4d5c98ddb479876f3a
parent3cc587ab8df80d42d9dab1a73a37701f565a3499 (diff)
downloadgame-5bdedeecea69a5892e3ce8854e85f78537cf7ca4.tar.gz
game-5bdedeecea69a5892e3ce8854e85f78537cf7ca4.zip
channel functions
-rw-r--r--reference/game.c807
-rw-r--r--src/containers.hh2
-rw-r--r--src/operate.cc391
-rw-r--r--src/operate.hh32
-rw-r--r--src/stubs.hh4
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);