Project1

标题: 关于单机游戏的机器码、兑换码 [打印本页]

作者: 暗羽星辰    时间: 2021-4-22 19:11
标题: 关于单机游戏的机器码、兑换码
本人小白一个、也不会写代码、现在准备弄游戏的兑换码、一头雾水
现在有大概思路、但不知道怎么做、有没有大佬来帮帮我~

需要一个数据库也就是搭服务器来保存当前用户的购买记录
游戏内部有个npc,对话这个npc输入自己的密码之后,连接网络
连接网络也就是连接数据库,判断这个代码到底是不是被发行过
如果是的话,对应什么物品,如果核对没有问题,就发礼包
但需要获得机器码
只有领取的地方才联网,只需要远程操作数据库的数据,不需要动游戏的代码

有没有大佬来帮帮我、先谢谢了!
作者: 任小雪    时间: 2021-4-22 19:30
你可以产生几个随机数,这几个数是玩家看得见的,然后通过一条公式将这几个随机数算出一个答案(玩家看不见),然后需要玩家输入这个答案,玩家不知道则只能问你这几个随机数对应的答案了
作者: xiamumomo    时间: 2021-4-22 19:42
MOG范例你可以下一下这个范例  里面有一个秘笈插件输入器  如果为了好看可以加一个事件绑定图片事件绑定图片教程评论附加插件地址  秘笈我倒是没用过他似乎事只要按出顺序就好了
作者: PLeaseS    时间: 2021-4-22 22:57
emmmm我游戏试玩版是有激活码的
一般试玩版发给别人我都会发一个不一样的激活码
但其实这些激活码都是AC24,BD35,CE46之类的规律数字,,,,

作者: 蹲厕所的女孩    时间: 2021-4-25 11:38
我寻思着单机游戏这种东西不都是弄成dlc的吗,为啥要用密钥这种麻烦还联网的操作
作者: fux2    时间: 2021-4-25 13:48
如果你要限量的话,一般还是得连服务器,如果对加密自信的话可以在游戏里存个列表
如果不限量可以设定一个公式,满足公式的就算正确的key
作者: 暗羽星辰    时间: 2021-4-28 04:35
PLeaseS 发表于 2021-4-22 22:57
emmmm我游戏试玩版是有激活码的
一般试玩版发给别人我都会发一个不一样的激活码
但其实这些激活码都是AC24 ...

激活码怎么弄?要写代码吗?不会写~
作者: 暗羽星辰    时间: 2021-4-28 04:35
fux2 发表于 2021-4-25 13:48
如果你要限量的话,一般还是得连服务器,如果对加密自信的话可以在游戏里存个列表
如果不限量可以设定一个 ...

公式写哪、怎么写、不太懂~
作者: fux2    时间: 2021-4-28 08:39
暗羽星辰 发表于 2021-4-28 04:35
公式写哪、怎么写、不太懂~

不懂的话不建议继续深入。
可以用最简单的数字兑换码来实现尝试一下,事件中有一个功能叫
“数值输入处理”,你可以通过这个接收玩家输入的一串数字,通过条件分歧
一个个判断玩家输入的码是否符合你的要求
作者: 暗羽星辰    时间: 2021-4-30 02:46
fux2 发表于 2021-4-28 08:39
不懂的话不建议继续深入。
可以用最简单的数字兑换码来实现尝试一下,事件中有一个功能叫
“数值输入处理 ...

大佬、这个最简单的倒是懂了、那你所说的公式是用什么语言写在哪的?
作者: 暗羽星辰    时间: 2021-4-30 03:10
任小雪 发表于 2021-4-22 19:30
你可以产生几个随机数,这几个数是玩家看得见的,然后通过一条公式将这几个随机数算出一个答案(玩家看不见) ...

请问这个是有限的吗?需要联网吗?
作者: 任小雪    时间: 2021-4-30 03:35
暗羽星辰 发表于 2021-4-30 03:10
请问这个是有限的吗?需要联网吗?

多元一次方程,几乎无限,但可能需要当面。
你没听懂我的意思。。。
解释起来好费时间。。。
比如,随机变量a到e等于1到9,
代入公式:(a+b/c的余数-d×e)的绝对值,
若随机出来的是,abcde都等于1,
y=(1+1/1的余数-1×1)的绝对值=0,
玩家如果输入答案0,则获得奖励,否则不获得。
若随机出来的是,abcde都等于2,
y=(2+2/2的余数-2×2)的绝对值=2,
玩家如果输入答案2,则获得奖励,否则不获得。

。。。。
作者: 任小雪    时间: 2021-4-30 03:36
用纯事件就可以实现,连代码都不用
作者: 任小雪    时间: 2021-4-30 03:40
当然,我的方法遇上数学大佬和有朋友分享游戏的(还有破解大师),那真的没辙
作者: fux2    时间: 2021-4-30 15:58
暗羽星辰 发表于 2021-4-30 02:46
大佬、这个最简单的倒是懂了、那你所说的公式是用什么语言写在哪的?

MV用的内置语言是js,实际上MV就是h5驱动
要说写在哪……三言两语也说不清啊,你学会之后想写在哪都行,我这里给你一个简单的例子吧



图中用的代码如下
JAVASCRIPT 代码复制
  1. const number = $gameVariables.value(46);
  2. if(number % 123 == 1) {
  3.   $gameSwitches.setValue(40,true);
  4. }


整个事件的顺序是:
1.重置兑换码的合法判定标记
2.接受玩家输入的数字(你用脚本的话这里就不需要是数字)
3.判断输入的数字和123取余,结果为1的话就判定合法
4.根据合法标记分歧事件
作者: zths    时间: 2021-4-30 21:25
首先一点  无法保证破解/作弊.
即使你有服务器也不好保证.
应对普通玩家的方法(可以防止玩家之间互相共享 "激活码")
下面的方法可以获取玩家系统的唯一标识并计算一个 "激活码"

你需要做的是在一个对话里调用显示 machineIdSync() 的返回值让玩家复制.
然后你使用 calcKey(机器码) 来生成key 并在游戏内做效验 calcKey(machineIdSync())  === "玩家输入的值"
正确就 "干啥" 否则 "怎样"
每次游戏读档后都进行效验.(要保存玩家输入的key)
代码最好要进行混淆,且calcKey 中的 //do some? 部分推荐进行小修小改..
本代码仅可保证在玩家不作弊 不修改你游戏工程的情况下的准确性.
  1. function machineIdSync(){
  2.     //from https://github.com/automation-stack/node-machine-id/blob/master/index.js
  3.     let execSync = require("child_process").execSync;
  4.     let exec = require("child_process").exec;
  5.     let createHash = require("crypto").createHash;
  6.     let win32RegBinPath = {
  7.         native: '%windir%\\System32',
  8.         mixed: '%windir%\\sysnative\\cmd.exe /c %windir%\\System32'
  9.     };
  10.     let guid = {
  11.             darwin: 'ioreg -rd1 -c IOPlatformExpertDevice',
  12.             win32: `${win32RegBinPath[isWindowsProcessMixedOrNativeArchitecture()]}\\REG.exe ` +
  13.                 'QUERY HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography ' +
  14.                 '/v MachineGuid',
  15.             linux: '( cat /var/lib/dbus/machine-id /etc/machine-id 2> /dev/null || hostname ) | head -n 1 || :',
  16.             freebsd: 'kenv -q smbios.system.uuid || sysctl -n kern.hostuuid'
  17.         }

  18.     function isWindowsProcessMixedOrNativeArchitecture() {
  19.         // detect if the node binary is the same arch as the Windows OS.
  20.         // or if this is 32 bit node on 64 bit windows.
  21.         if(process.platform !== 'win32') {
  22.             return '';
  23.         }
  24.         if( process.arch === 'ia32' && process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432') ) {
  25.             return 'mixed';
  26.         }
  27.         return 'native';
  28.     }

  29.     function hash(guid) {
  30.         return createHash('sha256').update(guid).digest('hex');
  31.     }

  32.     function expose(result) {
  33.         switch (process.platform) {
  34.             case 'darwin':
  35.                 return result
  36.                     .split('IOPlatformUUID')[1]
  37.                     .split('\n')[0].replace(/\=|\s+|\"/ig, '')
  38.                     .toLowerCase();
  39.             case 'win32':
  40.                 return result
  41.                     .toString()
  42.                     .split('REG_SZ')[1]
  43.                     .replace(/\r+|\n+|\s+/ig, '')
  44.                     .toLowerCase();
  45.             case 'linux':
  46.                 return result
  47.                     .toString()
  48.                     .replace(/\r+|\n+|\s+/ig, '')
  49.                     .toLowerCase();
  50.             case 'freebsd':
  51.                 return result
  52.                     .toString()
  53.                     .replace(/\r+|\n+|\s+/ig, '')
  54.                     .toLowerCase();
  55.             default:
  56.                 throw new Error(`Unsupported platform: ${process.platform}`);
  57.         }
  58.     }

  59.     function machineIdSync(original) {
  60.         let id = expose(execSync(guid[process.platform]).toString());
  61.         return original ? id : hash(id);
  62.     }

  63.     function machineId(original) {
  64.         return new Promise((resolve, reject) => {
  65.             return exec(guid[process.platform], {}, (err, stdout, stderr) => {
  66.                 if (err) {
  67.                     return reject(
  68.                         new Error(`Error while obtaining machine id: ${err.stack}`)
  69.                     );
  70.                 }
  71.                 let id = expose(stdout.toString());
  72.                 return resolve(original ? id : hash(id));
  73.             });
  74.         });
  75.     }
  76.     return machineIdSync();
  77. }

  78. function calcKey(machineId){
  79.     let hash = machineId;
  80.     //do some?
  81.     let hash8 = hash.match(/.{8}/g);
  82.     let hashi = [];
  83.     let key = undefined;
  84.     for(let i = 0; i < hash8.length; i++){
  85.         hashi[i] = parseInt(hash8[i],16);
  86.         if(key === undefined){
  87.             key = hashi[i];
  88.         }
  89.         key = Math.abs(key - hashi[i]);
  90.     }
  91.     key = Math.floor(Math.abs(key / 8));
  92.     return key;
  93. }
复制代码

作者: 暗羽星辰    时间: 2021-5-14 23:44
本帖最后由 暗羽星辰 于 2021-5-16 12:42 编辑
fux2 发表于 2021-4-30 15:58
MV用的内置语言是js,实际上MV就是h5驱动
要说写在哪……三言两语也说不清啊,你学会之后想写在哪都行, ...


谢谢大佬、这个应该直接就是兑换码吧?但是这个是无限的~
如果想要已经使用过的机器码不再出现、已经使用过的兑换码不能再使用、应该怎么设置?
或者怎么让同一个物品的机器码和兑换码是唯一的、除了卸载重装游戏、否则不变。
作者: 暗羽星辰    时间: 2021-5-16 12:41
任小雪 发表于 2021-4-30 03:35
多元一次方程,几乎无限,但可能需要当面。
你没听懂我的意思。。。
解释起来好费时间。。。

谢谢大佬、但是这个是无限的~
如果想要已经使用过的机器码不再出现、已经使用过的兑换码不能再使用、应该怎么设置?
或者怎么让同一个物品的机器码和兑换码是唯一的、除了卸载重装游戏、否则不变。
作者: 暗羽星辰    时间: 2021-5-24 20:49
zths 发表于 2021-4-30 21:25
首先一点  无法保证破解/作弊.
即使你有服务器也不好保证.
应对普通玩家的方法(可以防止玩家之间互相共享 " ...

虽然没看太懂、但还是谢谢大佬的帮助~
只能给一分、我也不知道为什么~




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1