Index: src/network/network_server.cpp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/network/network_server.cpp	(revision bd68ed916dc0733b6a8bd801bc96f9b2117abc6d)
+++ src/network/network_server.cpp	(revision )
@@ -1102,6 +1102,8 @@
 	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
 	NetworkClientInfo *ci = this->GetInfo();
+	// clear counter in case of any action
+	ci->afk_months_counter = 0;
 
 	if (err != NULL) {
 		IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, this->GetClientIP());
@@ -1394,6 +1396,9 @@
 	int64 data = p->Recv_uint64();
 
 	NetworkClientInfo *ci = this->GetInfo();
+	// clear counter in case of chat activity
+	ci->afk_months_counter = 0;
+
 	switch (action) {
 		case NETWORK_ACTION_GIVE_MONEY:
 			if (!Company::IsValidID(ci->client_playas)) break;
@@ -1937,6 +1942,24 @@
 /** Monthly "callback". Called whenever the month changes. */
 void NetworkServerMonthlyLoop()
 {
+		NetworkClientInfo *ci;
+		for (NetworkClientInfo *ci : NetworkClientInfo::Iterate())
+		{
+			// olewamy server
+			if ( ci->client_id == CLIENT_ID_SERVER ) continue;
+
+			// olewamy spectatorow
+			if ( ci->client_playas == INVALID_COMPANY ) continue;
+
+			// increase counter after end of the month
+			(ci->afk_months_counter)++;
+
+			if ( ci->afk_months_counter >= 12 )
+			{
+			    ci->afk_months_counter = 0;
+				NetworkServerDoMove( ci->client_id, INVALID_OWNER );
+			}
+		}
 	NetworkAutoCleanCompanies();
 	NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY);
 	if ((_cur_month % 3) == 0) NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY);
Index: src/network/network_base.h
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/network/network_base.h	(revision bd68ed916dc0733b6a8bd801bc96f9b2117abc6d)
+++ src/network/network_base.h	(revision )
@@ -31,6 +31,8 @@
 	CompanyID client_playas;                        ///< As which company is this client playing (CompanyID)
 	Date join_date;                                 ///< Gamedate the client has joined
 
+	int afk_months_counter;
+
 	/**
 	 * Create a new client.
 	 * @param client_id The unique identifier of the client.
Index: src/settings_type.h
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/settings_type.h	(revision bd68ed916dc0733b6a8bd801bc96f9b2117abc6d)
+++ src/settings_type.h	(revision )
@@ -267,6 +267,8 @@
 	char   last_host[NETWORK_HOSTNAME_LENGTH];            ///< IP address of the last joined server
 	uint16 last_port;                                     ///< port of the last joined server
 	bool   no_http_content_downloads;                     ///< do not do content downloads over HTTP
+	bool   move_afk_players_to_spectators;
+	uint16 move_afk_players_to_spectators_months;
 };
 
 /** Settings related to the creation of games. */
Index: src/table/settings.ini
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/table/settings.ini	(revision bd68ed916dc0733b6a8bd801bc96f9b2117abc6d)
+++ src/table/settings.ini	(revision )
@@ -3923,6 +3923,23 @@
 def      = false
 cat      = SC_EXPERT
 
+[SDTC_BOOL]
+ifdef    = ENABLE_NETWORK
+var      = network.move_afk_players_to_spectators
+flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+def      = false
+cat      = SC_EXPERT
+
+[SDTC_VAR]
+ifdef    = ENABLE_NETWORK
+var      = network.move_afk_players_to_spectators_months
+type     = SLE_UINT16
+flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+def      = 12
+min      = 1
+max      = UINT16_MAX
+cat      = SC_EXPERT
+
 ; Since the network code (CmdChangeSetting and friends) use the index in this array to decide
 ; which setting the server is talking about all conditional compilation of this array must be at the
 ; end. This isn't really the best solution, the settings the server can tell the client about should
