搜索
查看: 18905|回复: 121

【改进首发】显示IP及城市插件 for amx0.9.9详细制作方法!

[复制链接]
发表于 2005-1-20 15:14:55 | 显示全部楼层 |阅读模式 来自 湖南永州
通过2天的研究,终于做成了新的amx0.9.9版的显示IP、城市插件及新的IP数据库,在自己服务器运行无错误后,特贴出与大伙共享:
作者:hnroc
发表论坛:点通
参考文章:x86的“ [插件发布]显示IP,城市插件For amxx0.16 发布。作者eXtrA_Csharp和nwb13,插件策划x86”,金闪闪的“显IP城市插件的mysql安装提示”,其他一些关于mysql的教程。
软件要求:UltraEdit-32,Mysql v4.0以上,ip.sql(通过工具把qqwry.dat导出的IP数据库)
操作系统:windows2000
适合版本:amx0.9.9(其他版本或低版本未测试,不能保证运行)

一、建立mysql,这步可以参考本论坛金闪闪的“显IP城市插件的mysql安装提示”把附件里的ip.sql导入数据库;
二、重点讲讲如何制作数据库,如果您不想学习,那就直接跳到步骤三:
1、首先要找到qqwry.dat数据库,在网上搜索qq ip数据库,然后通过第三方软件把此.dat文件转成.sql文件,这些链接在x86的“ [插件发布]显示IP,城市插件For amxx0.16 发布。作者eXtrA_Csharp和nwb13,插件策划x86”都提到了;
2、用UE打开转换后的ip.sql,通过与x86发布的ip数据库(以下用x86.sql)比较,发现有几点不同:
A.x86.sql共分有六个字段,即初始地址,终结地址,城市名称占四个字段即:
3740803328 3740803839 广东省深圳市 广东省深圳市 广东省深圳市 福田区天威视讯
这样在显示时候出现重复地点,并且ip地址是通过计算了,不够直观;而ip.sql只有4个字段,即初试地址,终结地址,城市,地区:
'003.000.000.000',' 003.255.255.255',' 美国',' 新泽西通用电气公司'
这样在取值显示时不会出现重复地点,但由于IP地址没有经过运算,所以就必须用其他算法加以区别,后面说明如何判断ip地址;
B、x86.sql里的数据库好象不全,大概只有5万多条而且是2004年7月的数据,最新ip.sql更新时间为2005年1月10日,现在最新的是20日的,记录多达18万条记录包括从0.0.0.0-255.255.255.255,所以不管哪个地方的玩家基本上都能显示出来。
2、针对以上不同,我们就需要重新定义数据字段名建立新的表把原来的:
CREATE TABLE IF NOT EXISTS `ipdatau` (
`StartIP` bigint(20) unsigned NOT NULL default '0',
`EndIP` bigint(20) unsigned NOT NULL default '0',
`Country` varchar(128) default '',
`Prov` varchar(128) default NULL,
`City` varchar(128) default NULL,
`Address` varchar(255) default NULL,
UNIQUE KEY `PK_ipdatau` (`StartIP`)
) TYPE=MyISAM;
改为:
CREATE TABLE IF NOT EXISTS mytable (startip bigint(20),
endip bigint(20),country varchar(128),area varchar(128));
就可以了,这点我已经在附件的ip.sql加了,只要导入就可以了,包括自动创建表结构。
3、表结构做完了,但在导入上又遇到问题了由于startip和endip是数值型,所以把上面的'003.000.000.000',' 003.255.255.255',' 美国',' 新泽西通用电气公司'导入后,就变了,所以需要对ip.sql还要进行加工,从例子我们可以知道凡是IP在003.000.000.000至003.255.255.255都是同一地点,如果我们把IP中的"."去掉即003000000000~003255255255这正好可以拿来运算判断,所以运用UE里的替换功能把所有"."替换为"",这样所有的IP数据就转成连续的数字;
在原始ip.sql里面还存在个问题:
INSERT INTO
<From,To,Country,Area>
VALUES('003000000000',' 003255255255',' 美国',' 新泽西通用电气公司');
里面的<From,To,Country,Area>并不是表名称,而在步骤2里我们建立的表名是mytable,所以还需要UE里的替换功能把<From,To,Country,Area>替换为mytable;
这样数据库的修改工作基本上完成了,最后是汉化问题,由于amx0.9.9对utf-8字体必须前面要有个空格,否则会导致服务器down,所以我们还需要把所有中文的前加个空格,替换功能也能做到,至于低版本的不需要这不操作,amxx没用过,不知道是否要执行此操作;最后把所有字体转为utf-8保存退出,这样一个新的数据库就建成了。
因为IP地址经常变化,所以拿到新的qqwry.dat后,按此方法转换就可以随时更新IP数据库了。
三、插件制作(源代码如下):
在x86的“ [插件发布]显示IP,城市插件For amxx0.16 发布。作者eXtrA_Csharp和nwb13,插件策划x86”插件下做的修改!
主要功能:1、玩家在进入服务器后,会在屏幕左边中间用绿色字体显示玩家所在城市;
2、增加命令amx_hideop 1/0(默认是1)在mysql.cfg里追加,它的功能是隐藏拥有"a"权限的城市,即拥有"a"权限的玩家进入服务器后,屏幕上不显示其所在城市,只说明他是OP,地址隐藏字样;
3、增加命令say /city,玩家执行此命令后,把所有在服务器内的玩家的名字,IP,所在城市以MOTD的方式显示出来,同样如果有amx_hideop限制,拥有"a"权限的OP的IP及所在城市以*****代替。
#include <amxmod>
#include <amxmisc>
#include <mysql>

new g_country[32][32],g_city[32][32]
new g_buffer[512]
new sBuffer[2048]

public plugin_init() {
register_plugin("Look Ip and City","1.0","hnroc")
register_clcmd( "say /city", "cmdcity", 0, "- display city (MOTD)")
register_clcmd( "say city", "cmdcity", 0, "- display city (MOTD)")
register_cvar("amx_mysql_host","127.0.0.1")
register_cvar("amx_mysql_user","root")
register_cvar("amx_mysql_pass","")
register_cvar("amx_mysql_db","amx")
register_cvar("amx_hideop","1")
new filename[32]
get_basedir( filename , 31 )
server_cmd("exec %s/config/mysql.cfg" , filename)
}

public client_putinserver(id){
new host[64], username[32], password[32], dbname[32], error[32],query[512]
new ipb1[12],ipb2[12],ipb3[12],ipb4[12]
new userip[16],uip[16]
new ipp[32],pos
get_user_ip(id,userip,15,1)
//IP地址转换,由于这里取出的IP地址把多余的0去掉了,所以要把某些去掉的0补上,如:3.128.65.3(转换后成3128653),此IP属于上面例子的提到的范围,但在IP数据库内的地址却是3000000000~3255255255,无法进行运算,所以要把去掉的0补上才行,第一段3,由于是在最前面,多余的0可以去掉,第二段的128,它没有0所以也没有去,第三段的65,前面的0不能去掉,所以要补上成065,第四段的3,前面2个0也要补上成003,然后在它们合在一起成3128065003,这样就能实现条件的判断了;也许会有人说为什么不让第1段*1000000000+第2段*1000000+第3段*1000+第4段,这样结果不也能得出相同的结果吗?这个方法我也试过,但第1段*1000000000后数据会溢出从而导致结果不对,所以不此法不行。
copy(uip,16,userip)
while(replace(uip,16,"."," ")){}
parse(uip,ipb1,12,ipb2,12,ipb3,12,ipb4,12)
pos += format(ipp[pos],31-pos,"%s",ipb1)
if(str_to_num(ipb2)>=100)
pos += format(ipp[pos],31-pos,"%s",ipb2)
else if(str_to_num(ipb2)>=10)
pos += format(ipp[pos],31-pos,"0%s",ipb2)
else if(str_to_num(ipb2)>=1)
pos += format(ipp[pos],31-pos,"00%s",ipb2)
if(str_to_num(ipb3)>=100)
pos += format(ipp[pos],31-pos,"%s",ipb3)
else if(str_to_num(ipb3)>=10)
pos += format(ipp[pos],31-pos,"0%s",ipb3)
else if(str_to_num(ipb3)>=1)
pos += format(ipp[pos],31-pos,"00%s",ipb3)
if(str_to_num(ipb4)>=100)
pos += format(ipp[pos],31-pos,"%s",ipb4)
else if(str_to_num(ipb4)>=10)
pos += format(ipp[pos],31-pos,"0%s",ipb4)
else if(str_to_num(ipb4)>=1)
pos += format(ipp[pos],31-pos,"00%s",ipb4)
//这里以上就是实现补0的方法
get_cvar_string("amx_mysql_host",host,64)
get_cvar_string("amx_mysql_user",username,32)
get_cvar_string("amx_mysql_pass",password,32)
get_cvar_string("amx_mysql_db",dbname,32)
server_print("MYSQL: host %s, username %s, password %s, database name %s",host,username,password,dbname)
new dbc = mysql_connect(host,username,password,dbname,error,32)
format(query,511,"SELECT * FROM mytable WHERE startip<=%s AND endip>=%s",ipp,ipp)
if (dbc < 1 ){
server_print("[AMX] SQL Connection Failed!")
return PLUGIN_HANDLED
}
if (mysql_query(dbc,query) < 1){
mysql_error(dbc,error,127)
server_print("[AMX] MySQL error: can't load address: '%s'",error)
return PLUGIN_HANDLED
}
server_print("[AMX] SQL Connected! get data.")
while(mysql_nextrow(dbc) > 0 ){
mysql_getfield(dbc, 3, g_country[id], 31)
mysql_getfield(dbc, 4, g_city[id], 31)
}
mysql_close(dbc)
server_print("[AMX] SQL Connection closed!")
new ids[2]
ids[0]=id
set_task(8.0,"show_msg",0,ids,2,"",1)
return PLUGIN_CONTINUE
}

public show_msg(ids[2]){
new name[32],id,pos
id=ids[0]
if (get_cvar_num("amx_hideop")){
if (get_user_flags(id)&ADMIN_IMMUNITY) {
get_user_name(id,name,31)
pos += format(g_buffer[pos],511-pos," %s ",name)
pos += format(g_buffer[pos],511-pos,"进入服务器,他来自:,")
pos += format(g_buffer[pos],511-pos," 身份OP,地址隐藏,")
pos += format(g_buffer[pos],511-pos," 祝您玩的愉快!")
while(replace(g_buffer, 511, ",", "^n")){}
set_hudmessage(0, 255, 0, 0.05, 0.50, 2, 0.01, 8.0, 0.01, 3.0, 4)
show_hudmessage(0, g_buffer)
}
else{
get_user_name(id,name,31)
pos += format(g_buffer[pos],511-pos," %s ",name)
pos += format(g_buffer[pos],511-pos,"进入服务器,他来自:,")
pos += format(g_buffer[pos],511-pos,"%s%s,",g_country[id],g_city[id])
pos += format(g_buffer[pos],511-pos," 祝您玩的愉快,请不要作弊!")
while(replace(g_buffer, 511, ",", "^n")){}
set_hudmessage(0, 255, 0, 0.05, 0.50, 2, 0.01, 8.0, 0.01, 3.0, 4)
show_hudmessage(0, g_buffer)
}
}
else{
get_user_name(id,name,31)
pos += format(g_buffer[pos],511-pos," %s ",name)
pos += format(g_buffer[pos],511-pos,"进入服务器,他来自:,")
pos += format(g_buffer[pos],511-pos,"%s%s,",g_country[id],g_city[id])
pos += format(g_buffer[pos],511-pos," 祝您玩的愉快,请不要作弊!")
// client_print(0,print_chat,"[hnroc]: %s",g_buffer)
while(replace(g_buffer, 511, ",", "^n")){}
set_hudmessage(0, 255, 0, 0.05, 0.50, 2, 0.01, 8.0, 0.01, 3.0, 4)
// set_hudmessage(0, 255, 0, 0.05, 0.45, 0, 6.0, 10.0, 0.5, 0.15, 4)
show_hudmessage(0, g_buffer)
}
return PLUGIN_CONTINUE
}

public cmdcity(id){
new players[32],inum
new iLen = 0
get_players(players,inum)
iLen = format( sBuffer,2047, "<body bgcolor=#000000><font color=#FFB000><pre>" )
iLen += format( sBuffer[iLen],2047-iLen,"%2s %15s %22s^n"," 玩家ID"," 玩家IP"," 所在城市")
for( new i = 0; i < inum && 2047-iLen > 0; i++ ) {
new ip[32],name[32]
if(get_cvar_num("amx_hideop")){
if (get_user_flags(players)&ADMIN_IMMUNITY) {
get_user_name(players,name,31)
iLen += format(sBuffer[iLen],2047-iLen,"%1s %13s %21s^n",name,"*****","*****","*****")
}
else{
get_user_name(players,name,31)
get_user_ip(players,ip,31,1)
iLen += format(sBuffer[iLen],2047-iLen,"%1s %s %s%s^n",name,ip,g_country[players],g_city[players])
}
}
else{
get_user_name(players,name,31)
get_user_ip(players,ip,31,1)
iLen += format(sBuffer[iLen],2047-iLen,"%1s %s %s%s^n",name,ip,g_country[players],g_city[players])
}
}
show_motd(id, sBuffer, "Look City" )
return PLUGIN_HANDLED
}
找到mysql.cfg,打开在其里修改为:
amx_mysql_host "127.0.0.1"
amx_mysql_user "root"
amx_mysql_pass "123456"
amx_mysql_db "amx"
amx_hideop "1"
其中root为用户名,123456为你设置的密码,amx为创建的数据库并非表(mytable)

这样一套显示IP及城市的插件全部做好了!

题外话:此插件对反作弊也有一定的帮助,OP如果发现某一个地区的玩家作弊很猖獗,尤其是那种封了IP换个IP再进的玩家,通过它可以屏蔽这一地区所有玩家,比如一玩家是广东佛山作弊,屡教不改,可以在里面加入些语句,凡是广东佛山的用户进游戏一律kick,这样即使他换IP也进不来了,除非他换城市!我现在就在做这方面的事情,不过这样也屏蔽了其他没作弊的同一地区的人,是把双刃剑。

最近部分人把帖子做成收费帖,故此贴免费,不过您如果看了还请帮忙顶下,有什么疑问或不对的请回贴我会尽快回复!不知道能否置顶呀?hehe

也可以先到本服务器参观下!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注个册吧

×
发表于 2005-1-20 15:25:18 | 显示全部楼层 来自 河南三门峡
很强 顶了~ :thefinger  :76:  :45:

我来测试一下  好像编译amxx 提示 没有mysql.inc 不过编译成功了
安装试试 稍后汇报结果  :21:


唉 没有仔细看 我用amxx1.0 不对头 测试不通过 楼主能否在amxx1.0环境下给弄一个  :58:
回复

使用道具 举报

发表于 2005-1-20 16:11:41 | 显示全部楼层 来自 广东佛山
同志,你辛苦了

什么时候做个for amxx1.0的啊?
回复

使用道具 举报

 楼主| 发表于 2005-1-20 16:40:30 | 显示全部楼层 来自 湖南永州
Post by wzf828
很强 顶了~ :thefinger  :76:  :45:

我来测试一下  好像编译amxx 提示 没有mysql.inc 不过编译成功了
安装试试 稍后汇报结果  :21:


唉 没有仔细看 我用amxx1.0 不对头 测试不通过 楼主能否在amxx1.0环境下给弄一个  :58:


我对amxx没用过啊,因为amxx下的mysql命令可能与amx的不同,可能需要修改部分命令,明天我再研究下amxx
至于你开始说的没有mysql.inc,原因是你没加载mysql.dll!
回复

使用道具 举报

发表于 2005-1-20 17:00:19 | 显示全部楼层 来自 河南三门峡
不是没有加载mysql.dll的缘故吧 本身我机器运行牛牛的显示IP
地理位置插件已经正常运行的 刚才屏蔽了那个使用这个~  :41:

Post by hnroc
我对amxx没用过啊,因为amxx下的mysql命令可能与amx的不同,可能需要修改部分命令,明天我再研究下amxx
至于你开始说的没有mysql.inc,原因是你没加载mysql.dll!
回复

使用道具 举报

发表于 2005-1-20 18:29:57 | 显示全部楼层 来自 浙江嘉兴
Post by hnroc
通过2天的研究,终于做成了新的amx0.9.9版的显示IP、城市插件及新的IP数据库,在自己服务器运行无错误后,特贴出与大伙共享:
作者:hnroc
发表论坛:点通
参考文章:x86的“ [插件发布]显示IP,城市插件For amxx0.16 发布。作者eXtrA_Csharp和nwb13,插件策划x86”,金闪闪的“显IP城市插件的mysql安装提示”,其他一些关于mysql的教程。
软件要求:UltraEdit-32,Mysql v4.0以上,ip.sql(通过工具把qqwry.dat导出的IP数据库)

题外话:此插件对反作弊也有一定的帮助,OP如果发现某一个地区的玩家作弊很猖獗,尤其是那种封了IP换个IP再进的玩家,通过它可以屏蔽这一地区所有玩家,比如一玩家是广东佛山作弊,屡教不改,可以在里面加入些语句,凡是广东佛山的用户进游戏一律kick,这样即使他换IP也进不来了,除非他换城市!我现在就在做这方面的事情,不过这样也屏蔽了其他没作弊的同一地区的人,是把双刃剑。

最近部分人把帖子做成收费帖,故此贴免费,不过您如果看了还请帮忙顶下,有什么疑问或不对的请回贴我会尽快回复!不知道能否置顶呀?hehe

也可以先到本服务器参观下!


首先是赞扬:你好厉害啊!呵呵 ;
再就是楼主你的Amxx版本出来没???
三是你的“Mysql v4.0以上”,,Mysql_amxx.dll能正常连接了嘛,我上次试的时候,由于Mysql版本更新后,Mysql_amxx.dll就不能和Mysql正常连接了,你搞定没??
四是你的题外话真的很噢,有屏蔽功能的当然好喽,是比较难,是把双刃剑。
五是你的免费的精神真的是值得大家学习!
最后还是谢谢你,做是真的很好,期待你的Amxx版本!
回复

使用道具 举报

发表于 2005-1-20 18:30:36 | 显示全部楼层 来自 陕西西安
不错,写得很详细,加精
回复

使用道具 举报

发表于 2005-1-20 19:37:47 | 显示全部楼层 来自 福建龙岩
补充一点,他说得mysql是建立CS服务器同一台机器上的。如果你的mysql在另外地方。
就必须修改sma文件,直接加入访问。例如:
   register_cvar("amx_mysql_host","127.0.0.1")
   register_cvar("amx_mysql_user","root")
   register_cvar("amx_mysql_pass","")
   register_cvar("amx_mysql_db","amx")
改为
   register_cvar("amx_mysql_host","192.168.0.100")
   register_cvar("amx_mysql_user","amxip")
   register_cvar("amx_mysql_pass","")
   register_cvar("amx_mysql_db","amx")
为何这样,这是mysql的module的BUG。
:43:

因为root被限定在localhost登陆,你必须新建立amxip用户无密码访问amx数据库。
:wink:
回复

使用道具 举报

发表于 2005-1-20 20:52:58 | 显示全部楼层 来自 湖北襄阳
太详细了,好文!
回复

使用道具 举报

发表于 2005-1-20 22:42:25 | 显示全部楼层 来自 广东深圳
嗯~好极了。

强人越来越多了。。。。。
回复

使用道具 举报

游客
回复
您需要登录后才可以回帖 登录 | 注个册吧

快速回复 返回顶部 返回列表