#include "..\\Library\\pcbnet.as"

#ifdef NEOZC_SERVER
	#define LOG_STR	"SVR:"
#else
	#define LOG_STR "CLI:"
#endif

#define	DP_CLIENT_MAX		22

#define DPID_SYSMSG			0			; VXebZ[W
#define DPID_ALLPLAYERS		$FFFFFF00	; SɑM
#define DPID_SERVERPLAYER	1			; T[ovC[
#define DPID_UNKNOWN		$FFFFFFFF	; Ms

#define	DPSYS_DESTROYPLAYERORGROUP	5

; MIvV
#define	AMDPLAY_SEND_ARRAY_AUTO		5	; l^
#define	AMDPLAY_SEND_STRING			10	; ^

; Send Flag
#define	DP_DATA_PROPERTY	0
#define	DP_DATA_TYPE		1
#define	DP_SEND_TYPE		2
#define	DP_PRIORITY			3
#define	DP_TIMEOUT			4

#define	DP_SERVER_TCPPORT		2310
#define DP_SERVER_UDPPORT		2310

#define	DP_CLIENT_PORT_S		2350
#define	DP_CLIENT_PORT_E		2400

; VXepbZ[W
#define DP_SYSMSG_CLIENT_PORT	$FA000010
#define	DP_SYSMSG_PLAYERID		$FA000020

; NCAg
#define	DP_CLIENT_NOCONNECT		0		; ڑ
#define	DP_CLIENT_CONNECT		1		; ڑ
#define	DP_CLIENT_DISCONNECTING	2		; ؒf

goto *DP_End

#deffunc AMdplayInitialize str dp_game_name

#ifdef NEOZC_SERVER
dim DP_Client_TCPSocket, DP_CLIENT_MAX
dim	DP_Client_UDPSocket, DP_CLIENT_MAX
sdim DP_Client_IPAddr, DP_CLIENT_MAX, 64
dim DP_Client_TCP_Port, DP_CLIENT_MAX
dim DP_Client_UDP_Port, DP_CLIENT_MAX
dim DP_Client_Stat, DP_CLIENT_MAX
dim DP_Client_PID, DP_CLIENT_MAX
sdim info_buf, 32
#else
dim DP_Client_TCPSocket, 1
dim DP_Client_UDPSocket, 1
dim DP_Client_TCP_Port, 1
dim DP_Client_UDP_Port, 1
#endif

dim	dp_send_buf, 1024		; Mpobt@ (lp)
sdim dp_send_sbuf, 1024		; Mpobt@ (p)
dim dp_recv_buf, 1024		; Mpobt@

sdim DP_GameName, 64
sdim DP_IPAddr, 64
sdim DP_PlayerName, 64

	DP_GameName = dp_game_name

	DP_IPAddr = ""
	DP_Server_TCP_Port = 0
	DP_Server_UDP_Port = 0

	DP_PlayerName = "NEO]NONAME"

	DP_ServerID = DPID_SERVERPLAYER

	DP_MaxPlayers = 0
	DP_CurrentPlayers = 1

	DP_Server_TCPocket = 0
	DP_Server_UDPSocket = 0

	DP_PlayerID_a = 100

#ifdef NEOZC_SERVER
	repeat DP_CLIENT_MAX
		DP_Client_TCPSocket.cnt = 0
		DP_Client_UDPSocket.cnt = 0
		DP_Client_Stat.cnt = DP_CLIENT_NOCONNECT
	loop
#else
	DP_Client_TCPSocket.0 = 0
	DP_Client_UDPSocket.0 = 0
#endif
	
return

#deffunc AMdplaySetPlayerName str pl_name
	DP_PlayerName = pl_name
return

#deffunc AMdplayGetPlayerName var pl_name, int pid
;	pl_name = DP_PlayerName
	pl_name = "NEO]TEST"
return

#deffunc AMdplaySelectSpecifiedConnection str dest_addr, str port, int flag
	DP_IPAddr = dest_addr
	DP_Server_TCP_Port = DP_SERVER_TCPPORT
	DP_Server_UDP_Port = DP_SERVER_UDPPORT
return

#deffunc AMdplayHostSession str boot, int flag

	; ڑҋ@p|[g쐬
	tcpmake DP_Server_TCPSocket, DP_Server_TCP_Port
	if ( stat != 0 ) {
		dialog LOG_STR+"T[opTCP\Pbg쐬ł܂ł", 1 : end
	}

	; T[opUDP|[g쐬
	udpsock DP_Server_UDPSocket, DP_Server_UDP_Port
	if ( stat != 0 ) {
		dialog LOG_STR+"T[opUDP\Pbg쐬ł܂ł", 1 : end
	}

;	dialog LOG_STR +"Server TCP : " + DP_Server_TCP_Port + " UDP: " + DP_Server_UDP_Port

return

#deffunc AMdplaySetSession int session_num, int max_players
	DP_MaxPlayers = max_players
return

#deffunc AMdplayEnumSessionCount var session_cnt, str dp_game_name
	session_cnt = 1
return

#deffunc AMdplayEnumSessionName var dp_session_name, int dp_tmp, int dp_session_num
	dp_session_name = SESSION_NAME
return

#deffunc AMdplayJoinSession int dp_session_num

	; NCAgpTCP|[g쐬
	try_port = DP_CLIENT_PORT_S
	result = 0
	while  (( result == 0 ) && ( try_port <= DP_CLIENT_PORT_E ))
		tcpmake DP_Client_TCPSocket, try_port
		if ( stat == 0 ) {
			result = 1
			DP_Client_TCP_Port.0 = try_port
		}
		try_port++
	wend
	if ( result == 0 ) {
		dialog LOG_STR+"NCAgpTCP\Pbg쐬ł܂ł"
	}

	try_port = DP_Client_TCP_Port.0 + 1
	result = 0

	while (( result == 0 ) && (try_port <= DP_CLIENT_PORT_E))
		udpsock DP_Client_UDPSocket.0, try_port
		if ( stat == 0 ) {
			result = 1
			DP_Client_UDP_Port.0 = try_port
		}
		try_port++
	wend

	if ( result == 0 ) {
		dialog LOG_STR+"NCAgpUDP\Pbg쐬ł܂ł"
		return	
	}

;	dialog LOG_STR + "CLI TCP: " + DP_Client_TCP_Port.0+ " CLI UDP: " + DP_Client_UDP_Port.0

	tcpopen DP_Server_TCPSocket, DP_IPAddr, DP_Server_TCP_Port
	if ( stat != 0 ) {
		dialog LOG_STR+"T[opTCP|[gɐڑł܂ł"
		return
	}

	repeat 1000
		tcpiscon DP_Server_TCPSocket
		if ( stat == 1 ) {
			break		; ڑ
		}
		if ( stat == 2 ) {
			dialog LOG_STR+"T[opTCP\Pbgɐڑł܂ł"
			return		; G[
		}
		wait 1
	loop

	udpsock DP_Server_UDPSocket

	if ( stat != 0 ) {
		dialog LOG_STR+"T[opUDP\Pbgɐڑł܂ł"
		return
	}

	udpsendto DP_Server_UDPSocket, DP_IPAddr, DP_Server_UDP_Port

	if ( stat != 0 ) {
		return
	}

	; NCAgTCPUDP̃|[gԍT[oɒʒm
	dp_send_buf.0 = DP_SYSMSG_CLIENT_PORT
	dp_send_buf.1 = DP_Client_TCP_Port.0
	dp_send_buf.2 = DP_Client_UDP_Port.0
	udpsend dp_send_buf, 0, 12, DP_Server_UDPSocket
	if ( stat != 0 ) {
		dialog LOG_STR+"T[oUDP\PbgɑMs"
		return
	}

return

#deffunc AMdplaySetReceiveBuffer array recv_buf, int size
	dupptr DP_RecvBuf, varptr(recv_buf), size, 4
	DP_RecvBufSize = size
return

#deffunc AMdplaySetReceiveInfo array recv_info
	dup DP_RecvInfo, recv_info
return

#deffunc AMdplaySetResultVariable array resultv
	dup DP_ResultVar, resultv
return

#deffunc AMdplayGetPointer array send_flg
	dup DP_SendFlag, send_flg
return

#deffunc AMdplayGetMyID var my_id
#ifdef NEOZC_SERVER
	my_id = 1
	DP_ServerID = my_id
#else
	; PlayerIDM
	repeat 2000
		udprecv dp_recv_buf, 0, 16, DP_Client_UDPSocket.0
		if ( stat != 0 ) {
;			dialog LOG_STR+"Recv " + dp_recv_buf.0 + " " + dp_recv_buf.1
			if ( dp_recv_buf.0 == DP_SYSMSG_PLAYERID ) {
				my_id = dp_recv_buf.1
;				dialog LOG_STR+"Receive PID " + my_id
				break
			}
		}
		await 1
	loop

	; T[oTCP|[gڑ󂯕t
	repeat	1000
		tcpwait DP_Client_TCPSocket.0
		if ( stat == 1 ) {
			tcpaccept DP_Server_TCPSocket, DP_Client_TCPSocket.0
			if ( stat != 0 ) {
				dialog LOG_STR+"NCAgpTCP\PbgڑG["
			}
			break
		}
	loop

#endif

return

#deffunc AMdplayReceive var res_result
	res_result = 0

#ifdef NEOZC_SERVER
	repeat DP_CLIENT_MAX
		if ( DP_Client_Stat.cnt = DP_CLIENT_DISCONNECTING ) {
			DP_RecvInfo.0 = DPSYS_DESTROYPLAYERORGROUP
			DP_RecvInfo.4 = DP_Client_PID.cnt
			DP_Client_Stat.cnt = DP_CLIENT_NOCONNECT
			DP_Client_PID.cnt = 0
			res_result = -1
			return
		}
	loop

	gosub *DP_CheckNewEntry

	; TCP\Pbg̎M`FbN
	repeat DP_CLIENT_MAX
		if ( DP_Client_Stat.cnt == DP_CLIENT_CONNECT ) {
			tcpiscon DP_Client_TCPSocket.cnt
			if ( stat == 1 ) {
				tcprecv dp_recv_buf, 0, 1024, DP_Client_TCPSocket.cnt
				res_stat = stat
			}
			else {
				res_stat = 0
			}
			if ( res_stat != 0 ) {
				recv_cnt = stat
				res_result = 1
		
				DP_RecvInfo.0 = dp_recv_buf.0
	
				repeat recv_cnt
					p = cnt+1
					DP_RecvBuf.cnt = dp_recv_buf.p
				loop

				return
			}
		}
	loop

	; UDP\Pbg̎M`FbN
	udpcheck chk, DP_Server_UDPSocket
	if (chk == 0) {
		res_result = 0
		return
	}
	res_result = 1

	udpcount recv_cnt, DP_Server_UDPSocket
	if ( stat !=0 ) {
		dialog LOG_STR+"udpcount error"
		res_result = 0
		return
	}
	
	udprecv dp_recv_buf, 0, recv_cnt, DP_Server_UDPSocket
	if ( stat == 0 ) {
		dialog LOG_STR+"udprecv error"
		res_result = 0
		return
	}

;		dialog LOG_STR+"Recv " + DP_RecvInfo

	DP_RecvInfo.0 = dp_recv_buf.0
	
	repeat recv_cnt
		p = cnt+1
		DP_RecvBuf.cnt = dp_recv_buf.p
	loop

;	dialog LOG_STR+"AMDPlay Recv " + DP_RecvInfo.0 + " " + recv_cnt
#else
	tcprecv dp_recv_buf, 0, 1024, DP_Server_TCPSocket
	if ( stat != 0 ) {
		recv_cnt = stat
		res_result = 1
		
		DP_RecvInfo.0 = dp_recv_buf.0
	
		repeat recv_cnt
			p = cnt+1
			DP_RecvBuf.cnt = dp_recv_buf.p
		loop
	}
	else {
		udpcheck chk, DP_Client_UDPSocket.0
		if (chk == 0) {
			res_result = 0
			return
		}
		res_result = 1

		udpcount recv_cnt, DP_Client_UDPSocket.0
		if ( stat !=0 ) {
			dialog LOG_STR+"udpcount error"
			res_result = 0
			return
		}
	
		udprecv dp_recv_buf, 0, recv_cnt, DP_Client_UDPSocket.0
		if ( stat == 0 ) {
			dialog LOG_STR+"udprecv error"
			res_result = 0
			return
		}

		DP_RecvInfo.0 = dp_recv_buf.0

;		dialog LOG_STR+" INFO " + DP_RecvInfo + " " + info.0 + " " + info_0

		repeat recv_cnt
			p = cnt+1
			DP_RecvBuf.cnt = dp_recv_buf.p
		loop

		if ( DP_RecvInfo.0 == 41 ) {
			dupptr aaa_str, varptr(DP_RecvBuf), 1024, 2
			dialog "PL " + aaa_str + " " + recv_cnt
		}

;		dialog LOG_STR+"AMDPlay Recv " + DP_RecvInfo + " " + recv_cnt
	}

#endif

return

#deffunc AMdplayGetPlayerCount var players
	players = DP_CurrentPlayers
return

#deffunc AMdplayGetPlayerID var dp_server_id, int dp_tmp, int dp_flag
	dp_server_id = DP_ServerID
return



#deffunc AMDplaySend array sdata, int ssize, int flag, int pid

	if ( DP_SendFlag.DP_DATA_PROPERTY == AMDPLAY_SEND_ARRAY_AUTO ) {

;		dialog	LOG_STR+"AMDPlay Send " + DP_SendFlag.DP_DATA_TYPE + " " + sdata.0 + " " + ssize

		dp_send_buf.0 = DP_SendFlag.DP_DATA_TYPE

		repeat ssize/4
			p = cnt+1
			dp_send_buf.p = sdata.cnt
		loop

#ifdef NEOZC_SERVER
		if ( pid == DPID_ALLPLAYERS ) {
			repeat DP_CLIENT_MAX
				if ( DP_Client_Stat.cnt == DP_CLIENT_CONNECT ) {
					udpsendto DP_Client_UDPSocket.cnt, DP_Client_IPAddr.cnt, DP_Client_UDP_Port.cnt
					udpsend dp_send_buf, 0, (ssize+4), DP_Client_UDPSocket.cnt
				}
			loop
		}
		else {
			repeat DP_CLIENT_MAX
				if ( DP_Client_Stat.cnt == DP_CLIENT_CONNECT ) && ( DP_Client_PID.cnt == pid ) {
					tcpfail DP_Client_TCPSocket.cnt
					if ( stat == 0 ) {
						udpsendto DP_Client_UDPSocket.cnt, DP_Client_IPAddr.cnt, DP_Client_UDP_Port.cnt
						udpsend dp_send_buf, 0, (ssize+4), DP_Client_UDPSocket.cnt
						if ( stat != 0 ) {
							dialog "NCAgւ̑Ms"
						}
					}
					else {
						; NCAgؒfKv
						DP_Client_Stat.cnt = DP_CLIENT_DISCONNECTING
						udpclose DP_Client_UDPSocket.cnt
						tcpclose DP_Client_TCPSocket.cnt
						DP_CurrentPlayers--

;						dialog LOG_STR+ "CLIENT DISCONNECT"
					}
					break					
				}
			loop
		}
#else
		udpsend dp_send_buf, 0, (ssize+4), DP_Server_UDPSocket
		if ( stat != 0 ) {
			dialog LOG_STR+"T[oUDPMs"
		}
#endif
	}
	else {
		if ( Set_DataProperty == AMDPLAY_SEND_STRING ) {

			dp_send_sbuf = DP_SendFlag.DP_DATA_TYPE + sdata

#ifdef NEOZC_SERVER
			if ( pid == DPID_ALLPLAYERS ) {
				repeat DP_CLIENT_MAX
					if ( DP_Client_Stat.cnt == DP_CLIENT_CONNECT ) {
						udpsendto DP_Client_UDPSocket.cnt, DP_Client_IPAddr.cnt, DP_Client_UDP_Port.cnt
						udpsend dp_send_sbuf, 0, (ssize+4), DP_Client_UDPSocket.cnt
					}
				loop
			}
			else {
				if ( DP_Client_Stat.cnt == DP_CLIENT_CONNECT ) && ( DP_Client_PID.cnt == pid ) {
						udpsendto DP_Client_UDPSocket.cnt, DP_Client_IPAddr.cnt, DP_Client_UDP_Port.cnt
						udpsend dp_send_sbuf, 0, (ssize+4), DP_Client_UDPSocket.cnt					
				}
			}
#else
			udpsend dp_send_sbuf, 0, (ssize+4), DP_Server_UDPSocket
			if ( stat != 0 ) {
				dialog LOG_STR+"T[oUDPMs"
			}
#endif		
		}
		
;		dialog	LOG_STR+"AMDPlay Send " + Set_DataType + " " + sdata.0 + " " + ssize

	}

return

; VKڑ҂̃`FbN
*DP_CheckNewEntry
	tcpwait DP_Server_TCPSocket
	if ( stat == 1 ) {
		new_no = 255
		repeat DP_CLIENT_MAX
			if ( DP_Client_Stat.cnt == DP_CLIENT_NOCONNECT ) {
				new_no = cnt
				break
			}
		loop

		if ( new_no != 255 ) {
			tcpaccept DP_Client_TCPSocket.new_no, DP_Server_TCPSocket
			DP_CurrentPlayers++
			DP_Client_Stat.new_no = DP_CLIENT_CONNECT
			repeat 16
				info_buf.cnt = "\0"
			loop
			tcpinfo info_buf, DP_Client_TCPSocket.new_no
			instr str_index, info_buf, ":", 0
			strmid DP_Client_IPAddr.new_no, info_buf, 0, str_index
			strlen len, info_buf
			strmid port_str, info_buf, str_index+1, (len-str_index-1)

			; NCAgTCP/UDP|[gԍM
			repeat 1000
				udprecv dp_recv_buf, 0, 256, DP_Server_UDPSocket
				if ( stat != 0 ) {
					if ( dp_recv_buf.0 == DP_SYSMSG_CLIENT_PORT ) {
						DP_Client_TCP_Port.new_no = dp_recv_buf.1
						DP_Client_UDP_Port.new_no = dp_recv_buf.2
;						dialog LOG_STR+"CLI TCP Port " + dp_recv_buf.1 + " CLI UDP Port " + dp_recv_buf.2 + " " + stat + " " + cnt
						break
					}
				}
				await 1
			loop

			; NCAgpUDP\Pbg쐬
			udpsock DP_Client_UDPSocket.new_no
			if ( stat != 0 ) {
				dialog LOG_STR+"NCAgpUDP\Pbg쐬s"
			}
			
			; PlayerID蓖Ă
			DP_Client_PID.new_no = DP_PlayerID_a
			DP_PlayerID_a++
			dp_send_buf.0 = DP_SYSMSG_PLAYERID
			dp_send_buf.1 = DP_Client_PID.new_no
			
			udpsendto DP_Client_UDPSocket.new_no, DP_Client_IPAddr.new_no, DP_Client_UDP_Port.new_no
			udpsend dp_send_buf, 0, 8, DP_Client_UDPSocket.new_no
			if ( stat != 0 ) {
				dialog LOG_STR+"NCAgUDPMs"
			}

			; NCAgpTCP|[gI[v
			tcpopen DP_Client_TCPSocket.new_no, DP_Client_IPAddr.new_no, DP_Client_TCP_Port.new_no
			if ( stat != 0 ) {
				dialog LOG_STR+"NCAgpTCP|[gɐڑs"
			}

			repeat 1000
				tcpiscon DP_Client_TCPSocket.new_no
				if ( stat == 1 ) {
					break		; ڑ
				}
				if ( stat == 2 ) {
					dialog LOG_STR+"NCAgpTCP\Pbgɐڑł܂ł", 1 : end
					return		; G[
				}
				wait 1
			loop

		}
;		dialog LOG_STR+"New Entry"
	}
return


*DP_end

