From a6325af8d937fbf600362bacde389e6fa7d02719 Mon Sep 17 00:00:00 2001
From: gepard1984 <gepard1984@54d463be-8e91-2dee-dedb-b68131a5f0ec>
Date: Mon, 5 Mar 2012 00:08:28 +0000
Subject: - Guild Castle code cleanup:   - all changes to guild castle data are
 now handled first by map-server and only sent to char-server for saving   -
 ensured that changes made to guild castle during char-server disconnection
 time will be resent on reconnect   - actually removed definition of
 `MAX_GUILDCASTLE` (r15657)

git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@15658 54d463be-8e91-2dee-dedb-b68131a5f0ec
---
 src/char/int_guild.c |  24 +-------
 src/common/mmo.h     |   1 -
 src/map/chrif.c      |   3 +
 src/map/guild.c      | 156 ++++++++++++++++++++++++++++++---------------------
 src/map/guild.h      |   3 +-
 src/map/intif.c      |  10 +---
 src/map/mob.c        |  28 +++------
 src/map/mob.h        |   2 +-
 src/map/script.c     |  38 +++----------
 9 files changed, 119 insertions(+), 146 deletions(-)

diff --git a/src/char/int_guild.c b/src/char/int_guild.c
index 912ee8ab1..d0f41b541 100644
--- a/src/char/int_guild.c
+++ b/src/char/int_guild.c
@@ -1136,17 +1136,6 @@ int mapif_guild_castle_dataload(int fd, int sz, int *castle_ids)
 	return 0;
 }
 
-int mapif_guild_castle_datasave(int fd, int castle_id, int index, int value)
-{
-	WFIFOHEAD(fd, 9);
-	WFIFOW(fd, 0) = 0x3841;
-	WFIFOW(fd, 2) = castle_id;
-	WFIFOB(fd, 4) = index;
-	WFIFOL(fd, 5) = value;
-	WFIFOSET(fd, 9);
-	return 0;
-}
-
 //-------------------------------------------------------------------
 // Packet received from map server
 
@@ -1776,24 +1765,18 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
 
 	if (gc == NULL) {
 		ShowError("mapif_parse_GuildCastleDataSave: castle id=%d not found\n", castle_id);
-		mapif_guild_castle_datasave(fd, castle_id, index, value);
 		return 0;
 	}
 
 	switch (index) {
 		case 1:
-			if (gc->guild_id != value) {
+			if (log_inter && gc->guild_id != value) {
 				int gid = (value) ? value : gc->guild_id;
 				struct guild *g = idb_get(guild_db_, gid);
-				if (log_inter)
-					inter_log("guild %s (id=%d) %s castle id=%d\n",
-					          (g) ? g->name : "??", gid, (value) ? "occupy" : "abandon", castle_id);
+				inter_log("guild %s (id=%d) %s castle id=%d\n",
+				          (g) ? g->name : "??", gid, (value) ? "occupy" : "abandon", castle_id);
 			}
 			gc->guild_id = value;
-			if (gc->guild_id == 0) {
-				// Delete guardians.
-				memset(gc->guardian, 0, sizeof(gc->guardian));
-			}
 			break;
 		case 2: gc->economy = value; break;
 		case 3: gc->defense = value; break;
@@ -1812,7 +1795,6 @@ int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
 			return 0;
 	}
 	inter_guildcastle_tosql(gc);
-	mapif_guild_castle_datasave(fd, gc->castle_id, index, value);
 	return 0;
 }
 
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 6a81407ce..602a2e40b 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -106,7 +106,6 @@
 #define MAX_GUILDEXPULSION 32
 #define MAX_GUILDALLIANCE 16
 #define MAX_GUILDSKILL	15 // increased max guild skills because of new skills [Sara-chan]
-#define MAX_GUILDCASTLE 34	// Updated to include new entries for WoE:SE. [L0ne_W0lf]
 #define MAX_GUILDLEVEL 50
 #define MAX_GUARDIANS 8	//Local max per castle. [Skotlex]
 #define MAX_QUEST_DB 2000 //Max quests that the server will load
diff --git a/src/map/chrif.c b/src/map/chrif.c
index a75c48ecb..26c7b10cc 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -510,6 +510,9 @@ void chrif_on_ready(void)
 
 	//Re-save any storages that were modified in the disconnection time. [Skotlex]
 	do_reconnect_storage();
+
+	//Re-save any guild castles that were modified in the disconnection time.
+	guild_castle_reconnect(-1, 0, 0);
 }
 
 
diff --git a/src/map/guild.c b/src/map/guild.c
index 75f63b2ae..70f5361bb 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -1530,16 +1530,21 @@ int guild_broken_sub(DBKey key,void *data,va_list ap)
 }
 
 //Invoked on Castles when a guild is broken. [Skotlex]
-int castle_guild_broken_sub(DBKey key,void *data,va_list ap)
+int castle_guild_broken_sub(DBKey key, void *data, va_list ap)
 {
-	struct guild_castle *gc=(struct guild_castle *)data;
-	int guild_id=va_arg(ap,int);
+	char name[EVENT_NAME_LENGTH];
+	struct guild_castle *gc = data;
+	int guild_id = va_arg(ap, int);
 
 	nullpo_ret(gc);
 
-	if (gc->guild_id == guild_id)
-	{	//Save the new 'owner', this should invoke guardian clean up and other such things.
-		gc->guild_id = 0;
+	if (gc->guild_id == guild_id) {
+		// We call castle_event::OnGuildBreak of all castles of the guild
+		// You can set all castle_events in the 'db/castle_db.txt'
+		safestrncpy(name, gc->castle_event, sizeof(name));
+		npc_event_do(strcat(name, "::OnGuildBreak"));
+
+		//Save the new 'owner', this should invoke guardian clean up and other such things.
 		guild_castledatasave(gc->castle_id, 1, 0);
 	}
 	return 0;
@@ -1549,26 +1554,12 @@ int castle_guild_broken_sub(DBKey key,void *data,va_list ap)
 int guild_broken(int guild_id,int flag)
 {
 	struct guild *g = guild_search(guild_id);
-	struct guild_castle *gc = NULL;
-	DBIterator *iter = NULL;
 	struct map_session_data *sd = NULL;
 	int i;
-	char name[EVENT_NAME_LENGTH];
 
 	if(flag!=0 || g==NULL)
 		return 0;
 
-	//we call castle_event::OnGuildBreak of all castles of the guild
-	//you can set all castle_events in the castle_db.txt
-	iter = db_iterator(castle_db);
-	for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) {
-		if (gc->guild_id == guild_id) {
-			safestrncpy(name, gc->castle_event, sizeof(name));
-			npc_event_do(strcat(name, "::OnGuildBreak"));
-		}
-	}
-	dbi_destroy(iter);
-
 	for(i=0;i<g->max_member;i++){	// �M���h���U��ʒm
 		if((sd=g->member[i].sd)!=NULL){
 			if(sd->state.storage_flag == 2)
@@ -1716,60 +1707,99 @@ void guild_castle_map_init(void)
 	}
 }
 
-// �M���h��f�[�^�ύX�v��
-int guild_castledatasave(int castle_id,int index,int value)
+/**
+ * Setter function for members of guild_castle struct.
+ * Handles all side-effects, like updating guardians.
+ * Sends updated info to char-server for saving.
+ * @param castle_id Castle ID
+ * @param index Type of data to change
+ * @param value New value
+ */
+int guild_castledatasave(int castle_id, int index, int value)
 {
-	if( index == 1 )
-	{	//The castle's owner has changed? Update Guardian ownership, too. [Skotlex]
-		struct guild_castle *gc = guild_castle_search(castle_id);
-		int m = -1;
-		if (gc) m = map_mapindex2mapid(gc->mapindex);
-		if (m != -1)
-			map_foreachinmap(mob_guardian_guildchange, m, BL_MOB); //FIXME: why not iterate over gc->guardian[i].id ?
-	}
-	else
-	if( index == 3 )
-	{	// defense invest change -> recalculate guardian hp
-		struct guild_castle* gc = guild_castle_search(castle_id);
-		if( gc )
-		{
-			int i;
-			struct mob_data* gd;
-			for( i = 0; i < MAX_GUARDIANS; i++ )
-				if( gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL )
-						status_calc_mob(gd,0);
-		}
-	}
-
-	return intif_guild_castle_datasave(castle_id, index, value); // FIXME: it may fail if char-server is disconnected
-}
+	struct guild_castle *gc = guild_castle_search(castle_id);
 
-// �M���h��f�[�^�ύX�ʒm
-int guild_castledatasaveack(int castle_id,int index,int value)
-{
-	struct guild_castle *gc=guild_castle_search(castle_id);
-	if(gc==NULL){
+	if (gc == NULL) {
+		ShowWarning("guild_castledatasave: guild castle '%d' not found\n", castle_id);
 		return 0;
 	}
-	switch(index){
-	case 1: gc->guild_id = value; break;
-	case 2: gc->economy = value; break;
-	case 3: gc->defense = value; break;
-	case 4: gc->triggerE = value; break;
-	case 5: gc->triggerD = value; break;
-	case 6: gc->nextTime = value; break;
-	case 7: gc->payTime = value; break;
-	case 8: gc->createTime = value; break;
-	case 9: gc->visibleC = value; break;
+
+	switch (index) {
+	case 1: // The castle's owner has changed? Update or remove Guardians too. [Skotlex]
+	{
+		int i;
+		struct mob_data *gd;
+		gc->guild_id = value;
+		for (i = 0; i < MAX_GUARDIANS; i++)
+			if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL)
+				mob_guardian_guildchange(gd);
+		break;
+	}
+	case 2:
+		gc->economy = value; break;
+	case 3: // defense invest change -> recalculate guardian hp
+	{
+		int i;
+		struct mob_data *gd;
+		gc->defense = value;
+		for (i = 0; i < MAX_GUARDIANS; i++)
+			if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL)
+				status_calc_mob(gd, 0);
+		break;
+	}
+	case 4:
+		gc->triggerE = value; break;
+	case 5:
+		gc->triggerD = value; break;
+	case 6:
+		gc->nextTime = value; break;
+	case 7:
+		gc->payTime = value; break;
+	case 8:
+		gc->createTime = value; break;
+	case 9:
+		gc->visibleC = value; break;
 	default:
 		if (index > 9 && index <= 9+MAX_GUARDIANS) {
 			gc->guardian[index-10].visible = value;
 			break;
 		}
-		ShowError("guild_castledatasaveack: not found index=%d\n", index);
+		ShowWarning("guild_castledatasave: index = '%d' is out of allowed range\n", index);
 		return 0;
 	}
-	return 1;
+
+	if (!intif_guild_castle_datasave(castle_id, index, value)) {
+		guild_castle_reconnect(castle_id, index, value);
+	}
+	return 0;
+}
+
+void guild_castle_reconnect_sub(void *key, void *data, va_list ap)
+{
+	int castle_id = GetWord((int)key, 0);
+	int index = GetWord((int)key, 1);
+	intif_guild_castle_datasave(castle_id, index, *(int *)data);
+	aFree(data);
+}
+
+/**
+ * Saves pending guild castle data changes when char-server is 
+ * disconnected.
+ * On reconnect pushes all changes to char-server for saving.
+ */
+void guild_castle_reconnect(int castle_id, int index, int value)
+{
+	static struct linkdb_node *gc_save_pending = NULL;
+
+	if (castle_id < 0) { // char-server reconnected
+		linkdb_foreach(&gc_save_pending, guild_castle_reconnect_sub);
+		linkdb_final(&gc_save_pending);
+	} else {
+		int *data;
+		CREATE(data, int, 1);
+		*data = value;
+		linkdb_replace(&gc_save_pending, (void*)(MakeDWord(castle_id, index)), data);
+	}
 }
 
 // �M���h�f�[�^�ꊇ��M�i���������j
diff --git a/src/map/guild.h b/src/map/guild.h
index 3af5be6c4..ded8468d3 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -91,10 +91,9 @@ int guild_gm_change(int guild_id, struct map_session_data *sd);
 int guild_gm_changed(int guild_id, int account_id, int char_id);
 
 void guild_castle_map_init(void);
-int guild_castledataload(int castle_id,int index);
 int guild_castledatasave(int castle_id,int index,int value);
-int guild_castledatasaveack(int castle_id,int index,int value);
 int guild_castledataloadack(int len, struct guild_castle *gc);
+void guild_castle_reconnect(int castle_id, int index, int value);
 
 int guild_agit_start(void);
 int guild_agit_end(void);
diff --git a/src/map/intif.c b/src/map/intif.c
index 20d686c11..c0d9050c5 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -36,7 +36,7 @@ static const int packet_len_table[]={
 	 0, 0, 0, 0,  0, 0, 0, 0, -1,11, 0, 0,  0, 0,  0, 0, //0x3810
 	39,-1,15,15, 14,19, 7,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3820
 	10,-1,15, 0, 79,19, 7,-1,  0,-1,-1,-1, 14,67,186,-1, //0x3830
-	-1, 9, 0,14,  0, 0, 0, 0, -1,74,-1,11, 11,-1,  0, 0, //0x3840
+	-1, 0, 0,14,  0, 0, 0, 0, -1,74,-1,11, 11,-1,  0, 0, //0x3840
 	-1,-1, 7, 7,  7,11, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3850  Auctions [Zephyrus]
 	-1, 7, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3860  Quests [Kevin] [Inkfish]
 	-1, 3, 3, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3870  Mercenaries [Zephyrus]
@@ -749,7 +749,7 @@ int intif_guild_castle_datasave(int castle_id,int index, int value)
 	WFIFOB(inter_fd,4)=index;
 	WFIFOL(inter_fd,5)=value;
 	WFIFOSET(inter_fd,9);
-	return 0;
+	return 1;
 }
 
 //-----------------------------------------------------------------
@@ -1209,11 +1209,6 @@ int intif_parse_GuildCastleDataLoad(int fd)
 {
 	return guild_castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4));
 }
-// �M���h��f�[�^�ύX�ʒm
-int intif_parse_GuildCastleDataSave(int fd)
-{
-	return guild_castledatasaveack(RFIFOW(fd,2),RFIFOB(fd,4),RFIFOL(fd,5));
-}
 
 int intif_parse_GuildMasterChanged(int fd)
 {
@@ -2037,7 +2032,6 @@ int intif_parse(int fd)
 	case 0x383e:	intif_parse_GuildNotice(fd); break;
 	case 0x383f:	intif_parse_GuildEmblem(fd); break;
 	case 0x3840:	intif_parse_GuildCastleDataLoad(fd); break;
-	case 0x3841:	intif_parse_GuildCastleDataSave(fd); break;
 	case 0x3843:	intif_parse_GuildMasterChanged(fd); break;
 
 	//Quest system
diff --git a/src/map/mob.c b/src/map/mob.c
index 73d752702..e1c324ba1 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -548,11 +548,8 @@ static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t d
 				guild_castledatasave(md->guardian_data->castle->castle_id, 1, 0);
 			}
 		} else {
-			if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible )
-			{	//Safe removal of guardian.
-				md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0;
+			if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible)
 				guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
-			}
 			unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian.
 		}
 		return 0;
@@ -2512,13 +2509,10 @@ void mob_revive(struct mob_data *md, unsigned int hp)
 		clif_charnameack (0, &md->bl);
 }
 
-int mob_guardian_guildchange(struct block_list *bl,va_list ap)
+int mob_guardian_guildchange(struct mob_data *md)
 {
-	struct mob_data *md;
-	struct guild* g;
-
-	nullpo_ret(bl);
-	nullpo_ret(md = (struct mob_data *)bl);
+	struct guild *g;
+	nullpo_ret(md);
 
 	if (!md->guardian_data)
 		return 0;
@@ -2531,11 +2525,8 @@ int mob_guardian_guildchange(struct block_list *bl,va_list ap)
 			md->guardian_data->emblem_id = 0;
 			md->guardian_data->guild_name[0] = '\0';
 		} else {
-			if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible )
-			{	//Safe removal of guardian.
-				md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0;
-				guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
-			}
+			if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible)
+				guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0);
 			unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian.
 		}
 		return 0;
@@ -2545,11 +2536,8 @@ int mob_guardian_guildchange(struct block_list *bl,va_list ap)
 	if (g == NULL)
 	{	//Properly remove guardian info from Castle data.
 		ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id);
-		if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS )
-		{
-			md->guardian_data->castle->guardian[md->guardian_data->number].visible = 0;
-			guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
-		}
+		if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS)
+			guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0);
 		unit_free(&md->bl,CLR_OUTSIGHT);
 		return 0;
 	}
diff --git a/src/map/mob.h b/src/map/mob.h
index 0ad95ff19..be1c0220e 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -237,7 +237,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target);
 
 int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index);	// Spawning Guardians [Valaris]
 int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, unsigned int bg_id);
-int mob_guardian_guildchange(struct block_list *bl,va_list ap); //Change Guardian's ownership. [Skotlex]
+int mob_guardian_guildchange(struct mob_data *md); //Change Guardian's ownership. [Skotlex]
 
 int mob_randomwalk(struct mob_data *md,unsigned int tick);
 int mob_warpchase(struct mob_data *md, struct block_list *target);
diff --git a/src/map/script.c b/src/map/script.c
index 67e9e722e..3fa32d681 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -10145,7 +10145,7 @@ BUILDIN_FUNC(getcastledata)
 
 	if (gc == NULL) {
 		script_pushint(st,0);
-		ShowWarning("builtin_setcastledata: guild castle for map '%s' not found\n", mapname);
+		ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname);
 		return 1;
 	}
 
@@ -10182,43 +10182,21 @@ BUILDIN_FUNC(getcastledata)
 
 BUILDIN_FUNC(setcastledata)
 {
-	const char* mapname = mapindex_getmapname(script_getstr(st,2),NULL);
+	const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL);
 	int index = script_getnum(st,3);
 	int value = script_getnum(st,4);
-	struct guild_castle* gc = guild_mapname2gc(mapname);
+	struct guild_castle *gc = guild_mapname2gc(mapname);
 
 	if (gc == NULL) {
-		ShowWarning("builtin_setcastledata: guild castle for map '%s' not found\n", mapname);
+		ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname);
 		return 1;
 	}
 
-	switch (index) {
-		case 1:
-			gc->guild_id = value; break;
-		case 2:
-			gc->economy = value; break;
-		case 3:
-			gc->defense = value; break;
-		case 4:
-			gc->triggerE = value; break;
-		case 5:
-			gc->triggerD = value; break;
-		case 6:
-			gc->nextTime = value; break;
-		case 7:
-			gc->payTime = value; break;
-		case 8:
-			gc->createTime = value; break;
-		case 9:
-			gc->visibleC = value; break;
-		default:
-			if (index > 9 && index <= 9+MAX_GUARDIANS) {
-				gc->guardian[index-10].visible = value;
-				break;
-			}
-			ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index);
-			return 1;
+	if (index <= 0 || index > 9+MAX_GUARDIANS) {
+		ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index);
+		return 1;
 	}
+
 	guild_castledatasave(gc->castle_id, index, value);
 	return 0;
 }
-- 
cgit v1.2.3-70-g09d2