![]() |
||||||||||||
|
零基础开发openmp/SAMP服务器基础教程 - 第一章 - 打印版本 +- samp | open.mp 联机社区论坛 (https://open-mp.cn) +-- 板块: SA-MP (https://open-mp.cn/forumdisplay.php?fid=12) +--- 板块: 教程 (https://open-mp.cn/forumdisplay.php?fid=17) +--- 主题: 零基础开发openmp/SAMP服务器基础教程 - 第一章 (/showthread.php?tid=17) |
||||||||||||
零基础开发openmp/SAMP服务器基础教程 - 第一章 - 小鸟unsigned - 03-20-2026 零基础开发openmp/SAMP服务器基础教程 - 第一章写给完全没接触过编程的你零基础开发openmp/SAMP服务器基础教程一共有三个篇章,此为第一篇,按顺序学习阅读即可 引用:这篇文章不会让你马上写出任何代码。 你可能正处于这样的处境你玩过 SAMP 联机,看到别的服务器有各种有趣的玩法,心里想:这个我也想做。 然后你搜了一下教程,打开了一个 .pwn 文件,看到满屏的英文字母和括号符号,看不懂。然后关掉了。 这不是你的问题。是大多数教程默认你已经有一些基础,直接跳过了最重要的第一步——建立认知。 这篇文章就是来补这一步的。 理解底层逻辑引用:理解这些尤为重要,是一切的起点。本篇将优先使用新手能理解的大白话进行讲解。 计算机是一个非常听话但非常死板的工具,先忘掉代码,我们来聊聊计算机到底是什么。 比方说地图导航软件 你输入目的地,导航会告诉你:前方 200 米左转,然后直行 500 米,到达目的地。 导航给出的是一步一步的指令,你只需要跟着做。如果你在它说左转的时候右转了,它不会生气,也不会猜你的意思,它只会重新计算,继续给你下一条指令。 计算机就是这样的。 它只会严格地、一条接一条地执行你给它的指令。 它不会猜,不会发挥,不会应该是这个意思吧帮你圆场。你说什么,它做什么。你没说的,它绝对不做。 而编程,就是把你的想法翻译成计算机能看懂的指令。 这件事没有你想的那么神秘很多人会觉得这是某种神秘的技术,像外星文字一样难以理解。 但你其实每天都在做类似的事情。 假设你要告诉一个什么都不懂的人,怎么帮你冲一杯咖啡,你会怎么说? 你不能说帮我冲杯咖啡,因为他不知道冲咖啡是什么意思。 你需要说: 代码: 1. 走到茶水间你写的这份说明书,其实就是一段程序。 你是在把帮我冲咖啡这个模糊的想法,拆分成一步一步清晰的指令。 编程做的事情,和这个完全一样。 唯一的区别是:你的指令不是写给人看的,是写给计算机看的,所以要用计算机能懂的语法来写。 学编程,本质上是在学把事情说清楚,编程里真正难的不是记住语法,而是把你的想法说得足够清楚、足够准确,清楚到计算机能执行。想法是模糊的。你需要把它变得更具体,这就是代码背后的思维过程。语法是最后才出现的东西,在这之前,你要先把逻辑想清楚。 为什么代码要用奇怪的语法写?为什么不能直接用中文写?直接告诉电脑给玩家 100 块钱不行吗? 因为计算机本身只认识 0 和 1,它不理解任何人类语言。 所以人们发明了编程语言——它是人和计算机之间的翻译官。 编程语言的语法比中文严格得多,但也简单得多。 中文有几万个汉字,有各种语气、歧义、修辞。编程语言通常只有几十个固定的关键词,每一个词只有一个意思,没有歧义。 比如在 Pawn 里: 代码: if → 如果就这些,你能用的词总共就这么多。其他所有千变万化的功能,都是用这些基础词拼出来的。 所以,代码并不是在用一门你不认识的语言说话,它只是在用一套更严格的格式,表达你本来就会表达的逻辑。 不会就查,查了才会open.mp 有完整的官方文档,里面列出了所有可用的函数和回调,以及每个函数怎么用、参数是什么意思。 地址:https://open.mp/docs 养成看文档的习惯,这是最重要的自学能力。当你查了文档、搜了搜索引擎,还是搞不定,这时候可以去问人 不好的问法:为什么我的代码不行? 好的问法:我想实现玩家加入时显示欢迎消息,我写了这段代码(贴上代码),编译没有报错,但玩家加入时没有收到消息,请问可能是什么原因? 把你的代码、你的预期、你观察到的现象都说清楚,别人才能帮你快速定位问题。你描述问题的清晰程度,决定了你能得到帮助的速度。 报错,是编译器在帮你报错信息是编译器(帮你把代码翻译成计算机能运行的文件的工具)在帮你找问题。 报错信息通常会告诉你两件事:
就算是工作了十年的程序员,每天也在面对 bug(程序里的错误)。 但是pawn相对简单很多,熟悉了之后,有时都不需要实际测试都可以直接通过看代码预判出运行的效果。 进入正题Pawn 是什么Pawn 是一种为游戏服务器设计的轻量脚本语言,不是通用高级语言。 对于想学习编程的人来说,它是一个很好的起点——因为你写的代码可以立刻在游戏里看到效果,这种即时反馈会让你进步很快。 本质上,这是在用C 语言的思维写游戏逻辑。学会 Pawn 的人,以后转 C/C++、Rust 都很快。在国外有不少人通过 SA-MP 开发找到了工作,后来接触到了 C++、PHP、JavaScript 等更复杂的方向。 脚本文件是什么你写的 Pawn 代码保存在一个 .pwn 文件里,这就是你的脚本源码。写完后需要经过编译,把 .pwn 变成服务器能运行的 .amx 文件,服务器加载的是 .amx,不是 .pwn。代码: 你写的代码 编译 服务器运行这个过程就像你写了一份中文食谱,翻译成机器能理解的语言,机器才能按步骤操作。 单线程目前你只需要知道一件事:Pawn 服务器是单线程的。 单线程意味着:整个服务器只有一条流水线,所有逻辑、计算只能排着队一个一个处理,同一时间只能执行一条指令。 举个例子:假设你写了一段代码需要执行 1 秒钟,那在这 1 秒内,服务器上其他所有事情都会停下来等它跑完,包括玩家的移动同步、其他玩家的操作响应。 早期玩过 RPG 服的应该有印象——每到发薪日,服务器会卡顿一下。就是因为给所有玩家结算工资的代码在单线程里跑完之前,所有事件都被暂停了。 结论:写代码要注重性能,避免一段逻辑执行时间过长。单条简单的加减、判断代码几乎是瞬间完成的(微秒级别),这类代码完全不用担心。 理解 Tick(帧)open.mp 默认每秒运行 30 个 tick(帧),也就是每秒打包、更新、同步 30 次数据。 如果网络不好(玩家或服务器任意一方),就可能出现某次 tick 的数据包没有成功传输,也就是俗称的丢包。 比如连续两秒没收到玩家的位置数据,第三秒突然收到了,就会出现我们常见的瞬移现象。网络好的情况下,每帧数据几乎全部到达,玩家动作就很平滑。 即使你什么逻辑都没写,open.mp 每个 tick 也会自动同步这些基础数据:
从玩家操作到游戏表现,完整流程代码: 玩家操作不同的玩家操作,会触发不同的回调:
举个例子:友伤保护 当玩家开枪,触发 OnPlayerWeaponShot。在这个回调里,你可以判断被击中的是不是队友,如果是队友就让伤害为 0:代码: public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ)再举个例子:对话框治疗 当玩家操作对话框,触发 OnDialogResponse。判断玩家选了哪个选项,然后执行对应逻辑:代码: public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])引用:注意:
关于作弊服务器收到的数据,默认是信任客户端发来的。作弊工具就是利用这一点,篡改客户端发出的数据包(比如把血量改成 10000、位置瞬移到某处),服务器收到后会直接把这些数据同步给其他玩家,其他人就会看到无敌血条、飞天瞬移。 GetPlayerMoney 获取的就是客户端发来的金钱数据。如果你没有用服务端自己的变量记录玩家金钱,就相当于完全信任了客户端,没有任何验证。解决方法:重要的数据(血量、金钱、等级等)永远在服务端自己维护,不信任客户端发来的数值。 什么是回调(Callback)回调是服务端自动触发的函数,触发时机是服务端提前定好的,你不需要手动调用它。 你能做的是:在这个函数里写你自己的逻辑。 所有服务端自带的回调都以 public On 开头,比如:代码: public OnPlayerConnect(playerid)public 是什么意思public 表示这个函数是公开的,可以被服务端直接调用。服务端自带的回调必须加 public,否则服务端找不到它,触发时就不会执行你写的代码。return 1 是什么意思函数执行完毕后,需要返回一个结果告诉服务端处理完了。
具体每个回调返回 0 和 1 各代表什么,查文档就知道。新手阶段统一写 return 1 不会出大问题。每个回调都是一个独立的房间回调的范围 = 花括号 {} 包着的所有内容。从 { 到 } 之间的所有代码都属于这个回调。代码: public OnPlayerConnect(playerid)什么是函数函数是一个工具,你不需要知道它内部怎么实现的,只需要知道怎么用、给它传什么参数、它会做什么事。 就像微波炉:你不需要知道微波炉的电路原理,只需要把食物放进去、设好时间、按启动,它就帮你加热。 服务端自带大约 1000 个左右的函数,每个函数从名字上就能大致猜到它的作用: 代码: SetPlayerHealth(playerid, Float:health) // 设置玩家血量括号里是参数,告诉函数对谁做做什么。 能不能自己创建函数可以。当你发现一段代码要重复写很多次,就该把它打包成函数。 代码: // 没有函数:每次都要重复写代码: // 有了函数:打包一次,随时调用什么时候该建函数? 一段逻辑在两个以上的地方用到,或者逻辑比较复杂、需要给它起个名字方便理解,就建函数。 能不能用别人写好的函数可以,这就是安装插件和依赖库。 你不需要为了拧一颗螺丝自己炼钢做螺丝刀,直接去五金店买一把就好了。 别人做好的功能,打包成插件,你直接引入使用,不需要知道内部原理。 不过在用之前可以留意几点:
去哪里找? Github 搜索,或者 open.mp 官方推荐列表:https://open.mp/docs/awesome 回调的执行顺序回调不是按固定顺序排好的,而是由 tick 中收到了什么数据来决定。 玩家没有做某个操作,对应的回调就不会触发。 如果一个玩家在同一个 tick 内同时触发了多个操作(极罕见),服务器会把这些事件排成队列,在单线程里一个接一个处理。 但回调内部的代码,是严格从上到下一行一行执行的。 代码写在哪里所有实际运行的代码,都必须写在某个回调的花括号里面。 写在外面的只能是:变量声明、函数定义、常量定义。 你自己写的函数,不会自动运行,必须在某个回调里主动调用它,才会被执行: 代码: // 这个函数不会自动运行可以把服务器想象成一台自动售货机:投币(玩家操作)会触发里面固定的机械流程(服务端回调)。你想加功能,只能在原有流程的某个环节里接线(在回调里调用你自己写的函数),你的代码不会凭空自己运行。 决定你高度的关键因素掌握了上面这些,你已经理解了 open.mp 服务端运行的核心原理。剩下的,本质上都是数学和逻辑问题。 但有一件事只能靠你自己做:查文档。 你能实现什么功能,取决于你知道多少回调和函数的存在。不需要把所有函数都背下来,但你需要通过不断查阅,建立起自己的工具库认知——知道有什么工具可以用,需要的时候去查怎么用。 官方文档:https://open.mp/docs 交流群:673335567 新手最常犯的错误是:遇到不会的功能,直接问别人这个怎么做,但别人告诉你思路了,你又不知道用哪个函数实现。 根本原因是对现有工具了解太少。多看文档,多看别人的开源脚本,这是没有捷径的积累过程。 你知道的越多,能做的就越多。 #GTA# #圣安地列斯# #侠盗猎车手# #圣安地列斯联机# #samp# #gta联机# #gtasa联机# #openmp# #omp# #open.mp# #gtasa# 社区交流群: 673335567 论坛: https://open-mp.cn/ |