├── .editorconfig ├── .gitignore ├── .vscode ├── .gitignore ├── c_cpp_properties.json └── settings.json ├── README.md ├── build.sh ├── build_msys2.sh ├── cmds ├── cmd │ ├── area_set.c │ ├── bit_test.c │ ├── cat.c │ ├── color.c │ ├── data.c │ ├── emoji.c │ ├── eval.c │ ├── help.c │ ├── hi.c │ ├── loadall.c │ ├── mudinfo.c │ ├── mudlist.c │ ├── quit.c │ ├── tutorial.c │ ├── update.c │ ├── variables.c │ └── wizard.c ├── demo │ ├── 2.1.1.c │ ├── 2.1.2.c │ ├── 2.1.3.c │ ├── 2.1.4.c │ ├── 2.1.5.c │ ├── 2.1.6.c │ ├── 2.1.7.c │ ├── 2.1.8.c │ ├── 2.2.1.c │ ├── 2.4.1.c │ ├── 2.5.1.c │ ├── 3.2.1.c │ ├── 3.2.2.c │ ├── 3.3.1.c │ ├── 3.3.2.c │ ├── 4.1.1.c │ ├── 4.2.1.c │ ├── 5.1.1.c │ ├── 5.2.1.c │ ├── 5.3.1.c │ ├── 5.4.1.c │ ├── 5.7.1.c │ ├── 5.7.2.c │ ├── 5.7.3.1.c │ ├── 5.7.3.2.c │ ├── 5.7.3.c │ ├── 5.7.4.1.c │ ├── 5.7.4.2.c │ ├── 5.7.4.c │ ├── 5.7.5.1.c │ ├── 5.7.5.2.c │ ├── 5.7.5.3.c │ ├── 5.7.5.4.c │ ├── 5.7.5.c │ ├── 6.2.1.c │ ├── 6.2.2.c │ ├── 6.2.3.c │ ├── 6.3.1.c │ ├── 6.3.2.c │ ├── 6.4.1.c │ ├── 6.4.2.c │ ├── 7.2.1.1.c │ ├── 7.2.1.c │ ├── 7.2.2.c │ ├── 7.3.1.c │ ├── 8.2.1.c │ ├── 8.2.2.c │ ├── 8.3.6.c │ ├── QRcode.c │ ├── arraysort.c │ ├── bubblesort.c │ ├── insertionsort.c │ ├── mergesort.c │ ├── quicksort.c │ ├── selectionsort.c │ ├── socket_server.c │ ├── socket_status.c │ ├── socket_tcp_client.c │ ├── socket_tcp_server.c │ ├── socket_udp_client.c │ └── socket_udp_server.c ├── efun │ ├── all_inventory.c │ ├── call_other.c │ ├── call_out_info.c │ ├── children.c │ ├── clear_bit.c │ ├── deep_inventory.c │ ├── destruct.c │ ├── disable_commands.c │ ├── ed.c │ ├── enable_commands.c │ ├── environment.c │ ├── find_living.c │ ├── find_player.c │ ├── first_inventory.c │ ├── get_dir.c │ ├── heart_beats.c │ ├── livings.c │ ├── move_object.c │ ├── named_livings.c │ ├── new.c │ ├── next_inventory.c │ ├── objects.c │ ├── query_snoop.c │ ├── query_snooping.c │ ├── read_file.c │ ├── save_object.c │ ├── say.c │ ├── set_bit.c │ ├── set_heart_beat.c │ ├── set_living_name.c │ ├── shadow.c │ ├── shout.c │ ├── shutdown.c │ ├── snoop.c │ ├── strlen.c │ ├── test_bit.c │ ├── this_player.c │ └── users.c └── test │ ├── .gitignore │ ├── test.c │ └── test.h ├── config.cfg ├── config.ini ├── data └── .gitignore ├── fix_permission.sh ├── include ├── README ├── ansi.h ├── function.h ├── globals.h ├── localtime.h ├── origin.h ├── parser_error.h ├── runtime_config.h ├── socket_err.h └── type.h ├── inherit ├── area.c ├── clean_up.c ├── combat.c ├── dbase.c ├── living.c ├── maze.c ├── object.c ├── room.c ├── user1.c ├── user2.c ├── user3.c ├── user4.c ├── user5.c ├── user6.c └── verb.c ├── log └── .gitignore ├── run.bat ├── run.sh ├── system ├── daemons │ ├── combat_d.c │ ├── monster_d.c │ ├── qq_d.c │ └── virtual_d.c ├── etc │ ├── motd │ └── preload ├── kernel │ ├── master.c │ ├── simul_efun.c │ └── simul_efun │ │ ├── color.c │ │ └── json.c └── object │ ├── login.c │ ├── user.c │ └── void.c ├── tmp └── .gitignore ├── verbs ├── fight.c ├── go.c └── look.c ├── world ├── .gitignore ├── area.c ├── area.o ├── maze.c ├── maze │ └── 5-5.c ├── tower.c ├── world.c └── world │ ├── 0,0,0.c │ ├── 5,2,0.c │ └── npc │ ├── mob.c │ └── npc.c └── www ├── css └── xterm.min.css ├── favicon.ico ├── font └── NotoSansMono-VariableFont_wdth,wght.ttf ├── index.html └── js ├── main.js ├── widechar_width.js ├── xterm-addon-attach.min.js ├── xterm-addon-fit.min.js ├── xterm-addon-unicode14.js ├── xterm-addon-web-links.min.js └── xterm.min.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | cert.* 3 | driver* 4 | fluffos* 5 | -------------------------------------------------------------------------------- /.vscode/.gitignore: -------------------------------------------------------------------------------- 1 | launch.json 2 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "LPC", 5 | "includePath": [ 6 | "${workspaceFolder}/include/" 7 | ], 8 | "forcedInclude": [ 9 | "${workspaceFolder}/include/globals.h" 10 | ], 11 | "defines": [ 12 | "FLUFFOS", 13 | "MUDOS" 14 | ], 15 | "cStandard": "c89", 16 | "cppStandard": "c++11", 17 | "intelliSenseMode": "${default}" 18 | } 19 | ], 20 | "version": 4 21 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "C_Cpp.errorSquiggles": "Disabled", 3 | "editor.formatOnType": true, 4 | "files.autoGuessEncoding": true, 5 | "files.insertFinalNewline": true, 6 | "files.trimFinalNewlines": true, 7 | "files.trimTrailingWhitespace": true, 8 | "editor.renderWhitespace": "all" 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## LPC-TEST 2 | 3 | LPC 开发测试 LIB,配合 fluffos v2019 以上版本使用。 4 | 5 | 本 LIB 和 fluffos 自带的 testsuite 不同点是 testsuite 主要是驱动功能测试,本 LIB 除了基础 LPC语言教程代码(`/cmds/demo/`)外,另外提供具体游戏开发的功能模块演示,比如:玩家基础功能、游戏地图、虚拟迷宫、战斗和怪物变身等等,用更少的代码理解游戏开发的功能实现。 6 | 7 | ``` 8 | _\\|//_ 9 | (' . . ') 10 | ┌-----------------------------ooO-(_)-Ooo-----------------------------------┐ 11 | | ★ 欢迎光临,旅行者。 12 | | ★ 13 | | ★ LPMUD 启动文件加载顺序: 14 | | ★ 1. simul_efun (运行时配置文件中指定) 15 | | ★ 2. master (运行时配置文件中指定) 16 | | ★ 注意:所有文件都会自动#include (运行时配置文件中指定) 17 | | ★ 18 | | ★ MASTER 对象必须实现以下 apply 方法: 19 | | ★ get_root_uid - author_file - get_bb_uid - domain_file - creator_file 20 | | ★ 21 | | ★ 玩家连线流程: 22 | | ★ 1. 调用 MASTER 对象的 object connect(int port) 方法 23 | | ★ 2. 调用 object connect(int port) 方法传回对象的 object logon(void) 方法 24 | | ★ 25 | | ★ 所有对象加载时都会调用 MASTER 对象的以下 apply 方法: 26 | | ★ domain_file、author_file、creator_file 27 | | ★ 所有对象加载时都会调用对象本身的 void create(void) 方法(如果有) 28 | └---------------------------------------------------------------------------┘ 29 | 本项目为 LPMUD 开发学习用,配套教程:https://bbs.mud.ren/threads/3 30 | ``` 31 | 32 | ### 目录结构 33 | 34 | 以下为项目中所有文件的说明,目前结构比较简单,文件也不多,但演示了游戏开发的多数功能模块。 35 | 36 | ``` 37 | . 38 | ├── README.md 39 | ├── cmds 游戏指令 40 | │   ├── demo 教程演示指令 41 | │   │   └── ... 42 | │   ├── efun 教程 efun 指令 43 | │   │   └── ... 44 | │   ├── test 个人测试目录,你可以把自己的测试指令放在这里 45 | │   │   └── test.c 46 | │   └── cmd 基础指令 47 | ├── config.cfg 运行时配置文件精简版(FluffOS v2019) 48 | ├── config.ini 运行时配置文件注释版(FluffOS v2019) 49 | ├── data 存档目录 50 | ├── include 头文件目录 51 | │   ├── ansi.h 颜色控制头文件 52 | │   ├── globals.h 全局包含头文件 53 | │   └── ... (其它为驱动内置头文件) 54 | ├── inherit 功能继承模块 55 | │   ├── area.c 区域环境功能模块 56 | │   ├── clean_up.c 自动内存回收功能模块 57 | │   ├── combat.c 战斗功能模块 58 | │   ├── dbase.c 数据存档模块 59 | │   ├── living.c 生物对象公共模块 60 | │   ├── maze.c 迷宫环境功能实现模块 61 | │   ├── object.c 实体对象公共模块 62 | │   ├── room.c 普通环境功能模块 63 | │   ├── user1.c 玩家对象(实现指令功能模块) 64 | │   ├── user2.c 玩家对象(实现指令别名功能模块) 65 | │   ├── user3.c 玩家对象(实现智能消息功能模块) 66 | │   ├── user4.c 玩家对象(实现战斗功能模块) 67 | │   ├── user5.c 玩家对象(实现存档功能模块) 68 | │   ├── user6.c 玩家对象(其他功能模块) 69 | │   └── verb.c 自然语法解析指令功能模块 70 | ├── log 日志目录 71 | │   ├── author_stats 72 | │   ├── debug.log 游戏运行日志 73 | │   ├── domain_stats 74 | │   ├── error_handler 编译错误追踪日志 75 | │   └── log_error 错误及警告日志 76 | ├── system 系统目录 77 | │   ├── daemons 守护进程 78 | │   │   ├── combat_d.c 战斗守护进程 79 | │   │   ├── monster_d.c 魔物守护进程 80 | │   │   ├── qq_d.c QQ群消息守护进程(socket使用演示) 81 | │   │   └── virtual_d.c 虚拟对象守护进程 82 | │   ├── etc 系统配置目录 83 | │   ├── kernel 核心文件 84 | │   │   ├── master.c 主控文件 85 | │   │   └── simul_efun.c 模拟外部函数文件 86 | │   └── object 核对对象 87 | │   ├── login.c 连线对象 88 | │   ├── user.c 玩家对象 89 | │   └── void.c 90 | ├── tmp 临时文件目录 91 | ├── verbs 自然语法指令目录 92 | ├── world 游戏地区 93 | │   ├── area.c 区域模式环境 94 | │   ├── maze.c 迷宫 95 | │   ├── tower.c 通天塔 96 | │   ├── world 世界特别地区 97 | │   │   ├── npc NPC(包括魔物) 98 | │   │   ├── 0,0,0.c 99 | │   │   └── 5,2,0.c 100 | │   └── world.c 世界地区 101 | └── www WEBSOCKET 102 | └── ... 103 | ``` 104 | 105 | ### 运行 106 | 107 | 请使用 FluffOS 最新版本的驱动运行,启动方式: 108 | 109 | driver config.ini 110 | 111 | 如果要后台显示更多信息,可使用以下方式启动: 112 | 113 | driver config.ini -fdebug 114 | 115 | 如果要追踪游戏运行信息,可使用以下方式启动: 116 | 117 | driver config.ini --tracing trace_driver.json 118 | 119 | > Ubuntu和WSL系统可以运行`./build.sh`自动下载并编译驱动,运行`./run.sh`启动项目 120 | 121 | ### 提示 122 | 123 | ~~在游戏中可以收到QQ群消息,也可以发送消息到QQ群(302388378),如有任何困难,可以直接chat xxx 求帮助。~~ 124 | 125 | 126 | .__ .__ .___ 127 | | |__ ____ _____ ______ _ _____________| | __| _/ 128 | | | \ / _ \ / \_/ __ \ \/ \/ / _ \_ __ \ | / __ | 129 | | Y ( <_> ) Y Y \ ___/\ ( <_> ) | \/ |__/ /_/ | 130 | |___| /\____/|__|_| /\___ >\/\_/ \____/|__| |____/\____ | 131 | \/ \/ \/ \/ 132 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 更新系统软件包列表 4 | sudo apt update 5 | # 安装软件包及依赖库 6 | sudo apt install git bison build-essential autoconf automake cmake gcc g++ libjemalloc-dev zlib1g-dev libssl-dev libmysqlclient-dev libsqlite3-dev libpq-dev libpcre3-dev libevent-dev libicu-dev libdw-dev binutils-dev libgtest-dev telnet python3 -y 7 | 8 | # 如果 fluffos 目录不存在,则从 gitee 克隆 fluffos 仓库 9 | if [ ! -d "fluffos" ]; then 10 | git clone https://gitee.com/mudren/fluffos.git 11 | fi 12 | 13 | # 进入 fluffos 目录并拉取最新代码 14 | cd fluffos && git checkout . && git pull 15 | 16 | # 如果 build 目录已存在,则删除 17 | if [ -d "build" ]; then 18 | rm -rf build 19 | fi 20 | 21 | # 创建 build 目录并进入 22 | mkdir build && cd build 23 | 24 | # 记录开始时间 25 | starttime=`date +'%Y-%m-%d %H:%M:%S'` 26 | 27 | # 编译 fluffos,使用多线程编译,开启 SQLite 数据库和默认数据库支持 28 | cmake -DPACKAGE_DB_SQLITE=2 -DPACKAGE_DB_DEFAULT_DB=2 .. && make -j$(nproc) install 29 | 30 | # 记录结束时间 31 | endtime=`date +'%Y-%m-%d %H:%M:%S'` 32 | 33 | # 计算编译时间 34 | start_seconds=$(date --date=" $starttime" +%s); 35 | end_seconds=$(date --date="$endtime" +%s); 36 | 37 | # 输出编译时间 38 | echo Start: $starttime. 39 | echo End: $endtime. 40 | echo "Build Time: "$((end_seconds-start_seconds))"s." 41 | 42 | # 复制驱动至系统目录 43 | sudo cp bin/driver /usr/local/games/ 44 | -------------------------------------------------------------------------------- /build_msys2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 检查操作系统是否为 msys2 4 | if [[ $(uname -o) != "Msys" ]]; then 5 | echo "This script should be run under msys2." 6 | exit 1 7 | fi 8 | 9 | # 更新系统软件包列表 10 | pacman -Syu 11 | # 安装软件包及依赖库 12 | pacman --noconfirm -S --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-zlib mingw-w64-x86_64-pcre mingw-w64-x86_64-icu mingw-w64-x86_64-sqlite3 mingw-w64-x86_64-jemalloc mingw-w64-x86_64-gtest bison make 13 | 14 | # 如果 fluffos 目录不存在,则从 gitee 克隆 fluffos 仓库 15 | if [ ! -d "fluffos" ]; then 16 | git clone https://gitee.com/mudren/fluffos.git 17 | fi 18 | 19 | # 进入 fluffos 目录并拉取最新代码 20 | cd fluffos && git checkout . && git pull 21 | 22 | # 如果 build 目录已存在,则删除 23 | if [ -d "build" ]; then 24 | rm -rf build 25 | fi 26 | 27 | # 创建 build 目录并进入 28 | mkdir build && cd build 29 | 30 | # 记录开始时间 31 | starttime=`date +'%Y-%m-%d %H:%M:%S'` 32 | 33 | # 编译 fluffos,使用多线程编译,开启 SQLite 数据库和默认数据库支持 34 | cmake -G "MSYS Makefiles" -DPACKAGE_DB_SQLITE=2 -DPACKAGE_DB_DEFAULT_DB=2 .. && make -j$(nproc) install 35 | 36 | # 记录结束时间 37 | endtime=`date +'%Y-%m-%d %H:%M:%S'` 38 | 39 | # 计算编译时间 40 | start_seconds=$(date --date=" $starttime" +%s); 41 | end_seconds=$(date --date="$endtime" +%s); 42 | 43 | # 输出编译时间 44 | echo Start: $starttime. 45 | echo End: $endtime. 46 | echo "Build Time: "$((end_seconds-start_seconds))"s." 47 | 48 | # 复制驱动至LIB目录 49 | cp bin/driver.exe ../.. 50 | -------------------------------------------------------------------------------- /cmds/cmd/bit_test.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | int m, n; 4 | 5 | if (arg && sscanf(arg, "%d %d", m, n) == 2) 6 | { 7 | if (n < 1) 8 | { 9 | return notify_fail("最小位为 1 !\n"); 10 | } 11 | 12 | printf("数值 %d 的第 %d 位是 ", m, n); 13 | cecho(bitCheck(m, n)); 14 | printf("数值 %d 的第 %d 位设置为 1 后结果是 ", m, n); 15 | cecho(bitSet(m, n)); 16 | printf("数值 %d 的第 %d 位设置为 0 后结果是 ", m, n); 17 | cecho(bitClear(m, n)); 18 | } 19 | else 20 | { 21 | return notify_fail("格式:bit_test m n\n"); 22 | } 23 | 24 | return 1; 25 | } 26 | -------------------------------------------------------------------------------- /cmds/cmd/cat.c: -------------------------------------------------------------------------------- 1 | // 查看/cmds/demo/目录下源文件 2 | int main(object me, string arg) 3 | { 4 | if (!arg) 5 | return notify_fail("指令格式 : cat <档案名>\n 如 : cat 2.1.1\n"); 6 | 7 | sscanf(arg, "%s.c", arg); 8 | arg = "/cmds/demo/" + arg + ".c"; 9 | if (file_size(arg) < 0) 10 | { 11 | return notify_fail("没有找到这个实例,如果你要查看其他文件源码,可以使用 efun/read_file\n"); 12 | } 13 | else 14 | { 15 | write(read_file(arg)); 16 | } 17 | 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /cmds/cmd/color.c: -------------------------------------------------------------------------------- 1 | #include 2 | inherit CLEAN_UP; 3 | 4 | int main(object me, string arg) 5 | { 6 | int *rgb = ({0x00, 0x33, 0x66, 0x99, 0xcc, 0xff}); 7 | 8 | printf("ANSI颜色测试:\n"); 9 | for (int i = 30; i < 50; i++) 10 | { 11 | printf(SGR(i) "%d. 你好ABC■■■" NOR, i); 12 | if (i % 5) 13 | { 14 | write("\t"); 15 | } 16 | else 17 | { 18 | write("\n"); 19 | } 20 | } 21 | 22 | printf("\n\n256颜色测试:\n"); 23 | for (int i = 0; i < 256; i++) 24 | { 25 | printf(FCC(i) "%3d. 你好ABC" NOR, i); 26 | if (i % 5) 27 | { 28 | write("\t"); 29 | } 30 | else 31 | { 32 | write("\n"); 33 | } 34 | } 35 | 36 | printf("\nRGB颜色测试:\n"); 37 | for (int r = 0; r < sizeof(rgb); r++) 38 | { 39 | for (int g = 0; g < sizeof(rgb); g++) 40 | { 41 | for (int b = 0; b < sizeof(rgb); b++) 42 | { 43 | printf(RGB(rgb[r], rgb[g], rgb[b]) "%'0'2x%'0'2x%'0'2x\t" NOR, rgb[r], rgb[g], rgb[b]); 44 | } 45 | write("\n"); 46 | } 47 | write("\n"); 48 | } 49 | 50 | return 1; 51 | } 52 | 53 | int help() 54 | { 55 | write("color 指令用来测试客户端可支持的颜色模式。\n"); 56 | return 1; 57 | } 58 | -------------------------------------------------------------------------------- /cmds/cmd/data.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright: 2019, Mud.Ren 3 | File name: data.c 4 | Description: 管理员专用,显示指定对象资料 5 | Author: xuefeng 6 | Version: v1.0 7 | Date: 2019-03-12 8 | History: 9 | *****************************************************************************/ 10 | inherit CLEAN_UP; 11 | 12 | int main(object me, string arg) 13 | { 14 | mapping list, tlist; 15 | mixed *klist, *tlist2; 16 | object ob, ob1; 17 | string text, id, spec; 18 | int loop; 19 | 20 | if (arg) 21 | { 22 | sscanf(arg, "%s %s", spec, arg); 23 | if (arg == "-t" || arg == "-d") 24 | { 25 | spec = arg; 26 | arg = 0; 27 | } 28 | if (spec && spec != "-d" && spec != "-t") 29 | { 30 | arg = spec + " " + arg; 31 | spec = 0; 32 | } 33 | } 34 | 35 | if (!arg || arg == "") 36 | ob = me; 37 | else if (sscanf(arg, "%s in %s", arg, id) == 2) 38 | { 39 | ob1 = present(id, environment(me)); 40 | if (!ob1) 41 | ob1 = present(id, me); 42 | if (!ob1) 43 | return notify_fail("本地无此生物: " + id + "\n"); 44 | if (!ob = present(arg, ob1)) 45 | return notify_fail("该生物身上无此对象: " + arg + "\n"); 46 | } 47 | else if (arg == "here") 48 | ob = environment(me); 49 | else 50 | { 51 | arg = lower_case(arg); 52 | 53 | ob = present(arg, environment(me)); 54 | if (!ob) 55 | ob = find_player(arg); 56 | if (!ob) 57 | ob = find_living(arg); 58 | if (!ob) 59 | ob = present(arg, me); 60 | if (!ob) 61 | return notify_fail("Data: 无法找到此对象: " + arg + "。\n"); 62 | } 63 | 64 | list = ob->query_entire_dbase(); 65 | tlist = ob->query_entire_temp_dbase(); 66 | if (!mapp(list) && !mapp(tlist)) 67 | return notify_fail("Data: 此对象并没有任何的资料。\n"); 68 | 69 | if (mapp(list) && sizeof(list)) 70 | { 71 | klist = keys(list); 72 | klist = sort_array(klist, "sort_keys", this_object()); 73 | } 74 | 75 | if (mapp(tlist) && sizeof(tlist)) 76 | { 77 | tlist2 = keys(tlist); 78 | tlist2 = sort_array(tlist2, "sort_keys", this_object()); 79 | } 80 | 81 | if (!klist || !sizeof(klist)) 82 | return notify_fail("Data: 此对象并没有储存任何资料。\n"); 83 | 84 | if (!spec || spec == "-d") 85 | { 86 | text = "Object: " + base_name(ob) + ".c\n"; 87 | 88 | for (loop = 0; loop < sizeof(klist); loop++) 89 | { 90 | if (strlen(klist[loop]) > 7) 91 | text += klist[loop] + "\t: "; 92 | else 93 | text += klist[loop] + "\t\t: "; 94 | text += sprintf("%O \n", list[klist[loop]]); 95 | } 96 | text += "\n总共有 " + sizeof(klist) + " 个储存的资料。\n\n"; 97 | } 98 | else 99 | text = ""; 100 | 101 | if (!spec || spec == "-t") 102 | { 103 | text += "TEMP DATA :\n\n"; 104 | 105 | for (loop = 0; loop < sizeof(tlist2); loop++) 106 | { 107 | if (strlen(tlist2[loop]) > 7) 108 | text += tlist2[loop] + "\t: "; 109 | else 110 | text += tlist2[loop] + "\t\t: "; 111 | 112 | text += sprintf("%O \n", tlist[tlist2[loop]]); 113 | } 114 | text += "\n总共有 " + sizeof(tlist2) + " 个暂存的资料。\n\n"; 115 | } 116 | 117 | write(text); 118 | return 1; 119 | } 120 | 121 | // This function is used to sort the key array. 122 | 123 | int sort_keys(string one, string two) 124 | { 125 | return strcmp(one, two); 126 | } 127 | 128 | // This function strips out the secured props from the data array. 129 | int filter_props(string prop, object target) 130 | { 131 | return 1; 132 | } 133 | 134 | int help(object me) 135 | { 136 | write(@LONG 137 | 指令格式: data <-t|-d> <玩家|对象|here> 138 | 指令范例: data <-- 看自己的所有 data base 139 | data -t <-- 看自己的暂存资料 140 | data -d <-- 看自己的永久资料 141 | data -t here <-- 看所在房间的暂时资料 142 | data ivy <-- 看 ivy 这个玩家(或对象)的所有资料 143 | data cloth in ivy <-- 看 ivy 身上的 cloth 的资料 144 | 指令说明: 145 | 此命令让你可以观看所指定对象的资料,且将会以 more 的 146 | 方式输出,如果没有指定数,则自动以使用者为参数。其中的 -t 选 147 | 项可以显示暂时变数, -d 选项可以只显示永久变数, 所要看的对象 148 | 可以是玩家或任何对象。 149 | LONG ); 150 | return 1; 151 | } 152 | -------------------------------------------------------------------------------- /cmds/cmd/emoji.c: -------------------------------------------------------------------------------- 1 | // emoji.c 2 | 3 | int main(object me, string arg) 4 | { 5 | int x = 0x1f300; 6 | int i; 7 | 8 | write("\t"); 9 | for (i = 0; i < 16; i++) 10 | { 11 | printf("\t %x", i); 12 | } 13 | for (i = 0; i < 976; i++) 14 | { 15 | if (i % 16 == 0) 16 | { 17 | printf("\n%x\t", x); 18 | } 19 | printf("%c\t", x); 20 | x++; 21 | } 22 | write("\n\t"); 23 | for (i = 0; i < 16; i++) 24 | { 25 | printf("\t %x", i); 26 | } 27 | write("\n"); 28 | 29 | return 1; 30 | } 31 | 32 | int help() 33 | { 34 | write("emoji 指令用来显示MUD游戏客户端支持的emoji表情。\n"); 35 | return 1; 36 | } 37 | -------------------------------------------------------------------------------- /cmds/cmd/eval.c: -------------------------------------------------------------------------------- 1 | inherit CLEAN_UP; 2 | 3 | int main(object me, string arg) 4 | { 5 | object eval_ob; 6 | string filename, file; 7 | 8 | if (!wizardp(me)) 9 | { 10 | return 0; 11 | } 12 | 13 | filename = "/tmp/debug_eval_file.c"; 14 | 15 | /* clean up first */ 16 | if (file_size(filename) != -1) 17 | rm(filename); 18 | if (eval_ob = find_object(filename)) 19 | destruct(eval_ob); 20 | 21 | file = "#include \nmixed eval(object me) { " + arg + "; }\n"; 22 | write_file(filename, file, 1); 23 | printf("Result = %O\n", filename->eval(me)); 24 | 25 | return 1; 26 | } 27 | -------------------------------------------------------------------------------- /cmds/cmd/help.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(object me, string arg) 3 | { 4 | string help = @HELP $CYN$ 5 | _ _______ _______ _________ _______ _______ _________ 6 | ( \ ( ____ )( ____ \ \__ __/( ____ \( ____ \\__ __/ 7 | | ( | ( )|| ( \/ ) ( | ( \/| ( \/ ) ( 8 | | | | (____)|| | | | | (__ | (_____ | | 9 | | | | _____)| | | | | __) (_____ ) | | 10 | | | | ( | | | | | ( ) | | | 11 | | (____/\| ) | (____/\ | | | (____/\/\____) | | | 12 | (_______/|/ (_______/ )_( (_______/\_______) )_($NOR$ 13 | $YEL$--------------------------------------------------------------------$NOR$ 14 | LPC-TEST使用指南,刚登录游戏的玩家请输入 $HIY$tutorial$NOR$ 根据提示操作。 15 | 当你进入游戏后,会发现自己除了可以使用以下指令外,什么也做不了(不能动、不能看、不能说): 16 | $CYN$bit_test$NOR$ 位运算测试指令,如:bit_test 2 1 17 | $CYN$cat$NOR$ 教程示例代码查看指令,如:cat 2.1.1 18 | $CYN$color$NOR$ 颜色测试指令,显示你的客户端支持的颜色 19 | $CYN$data$NOR$ 存档数据查看指令,查看对象的可存档数据 20 | $CYN$emoji$NOR$ emoji字符列表,显示常用的emoji表情 21 | $CYN$eval$NOR$ 强大而简单的游戏测试指令,需wizard权限 22 | $CYN$help$NOR$ 显示帮助文件,也可以输入 help [cmd] 查看指令使用说明,如:help fight 23 | $CYN$hi$NOR$ 智能消息测试指令,可以和其他玩家打招呼 24 | $CYN$loadall$NOR$ 游戏代码调试用,加载所有文件到内存,看看是否有错 25 | $CYN$mudinfo$NOR$ 显示游戏信息,使用 mudinfo -v 可显示更多内容 26 | $CYN$quit$NOR$ 退出游戏 27 | $CYN$tutorial$NOR$ 游戏向导,可以逐步解锁更多能力,也可根据相关代码学习具体实现 28 | $CYN$update$NOR$ 代码更新指令,修改代码后使用此指令更新生效 29 | $CYN$variables$NOR$ 对象全局变量查看指令,能比 data 指令查看更多的内容 30 | $CYN$wizard$NOR$ 开启wizard权限,允许使用eval指令 31 | 32 | 当你输入$HIY$tutorial user$NOR$后,会解锁更多功能,你慢慢变的能看、能动、能说、能战斗。 33 | 34 | 另外还可以可以直接使用 efun 目录下的指令。具体有哪些指令和示例可以输入以下指令查看: 35 | $CYN$get_dir cmds/efun$NOR$ 36 | 37 | 提示:如有疑问,可以在输入$HIY$tutorial user3$NOR$后,在线$HIC$chat 问题内容$NOR$寻求QQ群中网友的帮助。 38 | HELP; 39 | string file; 40 | 41 | if (!arg) 42 | { 43 | write(ansi(help)); 44 | } 45 | else if (file_size(file = "/cmds/cmd/" + arg + ".c") > 0 || file_size(file = "/cmds/test/" + arg + ".c") > 0 || file_size(file = "/cmds/efun/" + arg + ".c") > 0 || file_size(file = "/verbs/" + arg + ".c") > 0) 46 | { 47 | notify_fail("有这个指令存在,但是并没有详细的说明文件。\n"); 48 | return file->help(); 49 | } 50 | else 51 | { 52 | return notify_fail("没有这个指令。\n"); 53 | } 54 | 55 | return 1; 56 | } 57 | -------------------------------------------------------------------------------- /cmds/cmd/hi.c: -------------------------------------------------------------------------------- 1 | // hi.c 2 | int main(object me, string arg) 3 | { 4 | object ob; 5 | if (arg &&ob = find_living(arg)) 6 | { 7 | if (ob == me) 8 | { 9 | msg("emote", "$ME热情的和$ME自己打招呼!", me); 10 | } 11 | else 12 | { 13 | msg("emote", "$ME热情的和$YOU打招呼!", me, ob); 14 | } 15 | } 16 | else 17 | { 18 | msg("emote", "$ME热情的和大家打招呼!", me); 19 | } 20 | 21 | return 1; 22 | } 23 | -------------------------------------------------------------------------------- /cmds/cmd/loadall.c: -------------------------------------------------------------------------------- 1 | #include 2 | inherit CLEAN_UP; 3 | 4 | int loadall(string dir); 5 | 6 | int main(object me, string dir) 7 | { 8 | if (!dir) 9 | dir = "/"; 10 | if (dir[ < 1] != '/') 11 | dir += "/"; 12 | if (file_size(dir) != -2) 13 | return notify_fail(dir + "目录不存在···\n"); 14 | 15 | write("check dir " + dir + "\n"); 16 | if (loadall(dir)) 17 | return 1; 18 | } 19 | 20 | int loadall(string dir) 21 | { 22 | string file, err, *dirs; 23 | 24 | if (!arrayp(get_dir(dir))) 25 | return 1; 26 | 27 | dirs = get_dir(dir); 28 | if (dir == "/") 29 | dirs = dirs - ({".git", ".vscode", "data", "log", "tmp", "www"}); 30 | if (dir == "/cmds/") 31 | dirs = dirs - ({"test", "demo"}); 32 | 33 | foreach (file in dirs) 34 | { 35 | if (member_array(file, ({"simul_efun", "master"})) > -1) 36 | continue; 37 | 38 | reset_eval_cost(); 39 | switch (file_size(dir + file)) 40 | { 41 | case -1: 42 | //无法读取该目录,跳过 43 | break; 44 | case -2: 45 | if (file != "." && file != "..") 46 | call_out("loadall", 1, dir + file + "/"); 47 | break; 48 | default: 49 | if ((dir + file)[ < 2.. < 1] == ".c") 50 | { 51 | if (err = catch (load_object(dir + file))) 52 | cecho("loadall", "\n\tcheck : " + dir + file + "\n" + err); 53 | } 54 | } 55 | } 56 | write("check dir " + dir + " is ok.\n"); 57 | return 1; 58 | } 59 | -------------------------------------------------------------------------------- /cmds/cmd/mudinfo.c: -------------------------------------------------------------------------------- 1 | #include 2 | inherit CLEAN_UP; 3 | 4 | string duration() 5 | { 6 | int t, d, h, m, s; 7 | string time; 8 | 9 | t = uptime(); 10 | s = t % 60; 11 | t /= 60; 12 | m = t % 60; 13 | t /= 60; 14 | h = t % 24; 15 | t /= 24; 16 | d = t; 17 | 18 | if (d) 19 | time = d + "天"; 20 | else 21 | time = ""; 22 | 23 | if (h) 24 | time += h + "小时"; 25 | if (m) 26 | time += m + "分"; 27 | time += s + "秒"; 28 | 29 | return time; 30 | } 31 | 32 | int main(object me, string arg) 33 | { 34 | string msg; 35 | if (arg == "-v") 36 | { 37 | write("\nMUD 名称:" + MUD_NAME + "\n"); 38 | write("驱动环境:" + __ARCH__ + "\n"); 39 | write("驱动版本:" + __VERSION__ + "\n"); 40 | write("执行效率:" + query_load_average() + "\n"); 41 | write("内存占用:" + memory_info() / 1024 / 1024 + "M\n"); 42 | write("运行时间:" + duration() + "\n"); 43 | write("在线玩家:" + sizeof(users()) + "人\n"); 44 | write("游戏生物:" + sizeof(livings()) + "位\n"); 45 | write("载入对象:" + sizeof(objects()) + "个\n"); 46 | } 47 | else 48 | { 49 | msg = WHT BBLU "\n Mud名称 运行时间 游戏地址 端口 在线人数" NOR; 50 | msg += "\n─────────────────────────────────────────────────────────────\n"; 51 | msg += sprintf(" %-14s%-20s%-11s%-10d%-5d" NOR, MUD_NAME, duration(), "127.0.0.1", __PORT__, sizeof(users())); 52 | msg += "\n─────────────────────────────────────────────────────────────\n"; 53 | write(msg); 54 | } 55 | 56 | return 1; 57 | } 58 | -------------------------------------------------------------------------------- /cmds/cmd/mudlist.c: -------------------------------------------------------------------------------- 1 | /** 2 | * sockets DATAGRAM 模式客户端测试:mudlist 3 | */ 4 | #include 5 | 6 | #define MODE 2 7 | #define MUD_DNS "118.190.104.241 5567" 8 | 9 | nosave int Socket; 10 | nosave mixed *List = ({}); 11 | 12 | void read_callback(int fd, mixed message, string addr) 13 | { 14 | // debug(sprintf("fd = %d, addr = %s", fd, addr)); 15 | // debug(json_decode(message)); 16 | List += ({json_decode(message)}); 17 | } 18 | 19 | private void socket_init() 20 | { 21 | // 创建一个 efun socket 连接 22 | Socket = socket_create(MODE, "read_callback"); 23 | // 如果不绑定端口,将使用随机端口连接服务器,但无法收到服务端返回的消息 24 | socket_bind(Socket, 7899); 25 | if (Socket < 0) 26 | { 27 | cecho("【Warning】socket_create error: " + socket_error(Socket)); 28 | } 29 | else 30 | { 31 | int err; 32 | // UDP 发送消息到服务器 33 | err = socket_write(Socket, "mudlist", MUD_DNS); 34 | if (err < 0) 35 | { 36 | cecho("【Warning】socket_write error: " + socket_error(err)); 37 | // socket_close(Socket); 38 | } 39 | } 40 | } 41 | 42 | void create() 43 | { 44 | socket_init(); 45 | } 46 | 47 | void reset( void ) 48 | { 49 | debug("开始更新mudlist 🧡💛💚"); 50 | List = ({}); 51 | socket_write(Socket, "mudlist", MUD_DNS); 52 | } 53 | 54 | int main(object me, string arg) 55 | { 56 | string output; 57 | 58 | if (arg == "-U") 59 | { 60 | reset(); 61 | } 62 | 63 | if (!sizeof(List)) 64 | return notify_fail("MUDLIST更新中,请稍后查看 💞\n"); 65 | 66 | output = WHT BBLU " MUD名称 MUD 地址 在线人数 驱动·版本 " NOR 67 | "\n---------------------------------------------------------------------------\n"; 68 | foreach(mapping mud in List) 69 | { 70 | if (undefinedp(mud["USERS"])) 71 | { 72 | // continue; 73 | mud["USERS"] = "--"; 74 | } 75 | 76 | output += sprintf(" %-25s%-25s%-12s%-s" NOR + "\n", 77 | mud["MUDNAME"]||mud["NAME"], mud["HOSTADDRESS"]+":"+mud["PORT"], 78 | mud["USERS"],mud["DRIVER"]||mud["VERSION"]); 79 | } 80 | output += "---------------------------------------------------------------------------\n"; 81 | 82 | if (objectp(me)) 83 | printf(output); 84 | else 85 | write(output + "\n"); 86 | 87 | return 1; 88 | } 89 | 90 | int help() 91 | { 92 | write(@HELP 93 | 指令格式 : mudlist [-U] 94 | 95 | 这个指令让你列出目前跟这个 Mud 取得联系中的其他 Mud。 96 | HELP ); 97 | return 1; 98 | } 99 | -------------------------------------------------------------------------------- /cmds/cmd/quit.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | say("玩家(" + geteuid(me) + ")退出了游戏。\n"); 4 | destruct(me); 5 | 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/cmd/tutorial.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define USER1 "/inherit/user1" 4 | #define USER2 "/inherit/user2" 5 | #define USER3 "/inherit/user3" 6 | #define USER4 "/inherit/user4" 7 | #define USER5 "/inherit/user5" 8 | #define USER6 "/inherit/user6" 9 | 10 | int main(object me, string arg) 11 | { 12 | object user; 13 | 14 | if (!arg && !me->query_temp("step")) 15 | { 16 | cecho("欢迎光临!\n"); 17 | cecho("你当前玩家对象是:" + sprintf("%O", me)); 18 | cecho("你当前所在环境是:" + file_name(environment(me))); 19 | cecho("提示:现在你不能动、不能看、不能说,输入 tutorial 1 看看会发生什么吧。"); 20 | return 1; 21 | } 22 | 23 | switch (arg) 24 | { 25 | case "1": 26 | if (me->query_temp("step") != 1) 27 | { 28 | user = new (USER1, geteuid(me)); 29 | user->set_temp("step", 1); 30 | exec(user, me); 31 | destruct(me); 32 | cecho("恭喜,成功啦!\n"); 33 | cecho("你当前玩家对象是:" + sprintf("%O", user)); 34 | cecho("你当前所在环境是:" + file_name(environment(user))); 35 | cecho("提示:现在你在新的环境中了,输入 look 或 l 看看吧。"); 36 | cecho("提示:你可以使用更多指令了,如 say shout shutdown 等"); 37 | cecho("提示:你可以使用 east south west north 移动啦"); 38 | cecho("\n相关教程:https://bbs.mud.ren/threads/47\n"); 39 | cecho("提示:现在移动必须输入完整的方向,非常不方便,输入 tutorial 2 试试吧。"); 40 | } 41 | else 42 | { 43 | cecho("你当前就在此状态,无需重复操作!"); 44 | } 45 | break; 46 | case "2": 47 | if (me->query_temp("step") != 2) 48 | { 49 | user = new (USER2, geteuid(me)); 50 | user->set_temp("step", 2); 51 | exec(user, me); 52 | destruct(me); 53 | cecho("恭喜,成功啦!\n"); 54 | cecho("你当前玩家对象是:" + sprintf("%O", user)); 55 | cecho("提示:你可以更方便的移动了: e s w n"); 56 | cecho("提示:你还可以使用更多指令了,如 chat、who、i、ls"); 57 | cecho("\n相关教程参考:https://bbs.mud.ren/threads/48\n"); 58 | cecho("提示:你现在有很多消息看不到,不信可以输入 hi 试试"); 59 | cecho("提示:如果想看到更多信息,输入 tutorial 3 试试吧。"); 60 | } 61 | else 62 | { 63 | cecho("你当前就在此状态,无需重复操作!"); 64 | } 65 | break; 66 | case "3": 67 | if (me->query_temp("step") != 3) 68 | { 69 | user = new (USER3, geteuid(me)); 70 | user->set_temp("step", 3); 71 | exec(user, me); 72 | destruct(me); 73 | cecho("恭喜,成功啦!\n"); 74 | cecho("你当前玩家对象是:" + sprintf("%O", user)); 75 | cecho("提示:你的人物可以看到更多消息了,包括其它玩家从你身边走过的提示等等"); 76 | cecho("提示:现在开始,你可以看到QQ群消息了,有问题直接在游戏中 chat 和群中玩家交流吧"); 77 | cecho("提示:你的人物还可以偷窥别人了,对其他玩家输入 snoop 试试。"); 78 | cecho("\n相关教程参考:https://bbs.mud.ren/threads/53\n"); 79 | cecho("提示:如果想体验战斗,输入 tutorial 4 试试吧。"); 80 | } 81 | else 82 | { 83 | cecho("你当前就在此状态,无需重复操作!"); 84 | } 85 | break; 86 | case "4": 87 | if (me->query_temp("step") != 4) 88 | { 89 | user = new (USER4, geteuid(me)); 90 | user->set_temp("step", 4); 91 | exec(user, me); 92 | destruct(me); 93 | cecho("恭喜,成功啦!\n"); 94 | cecho("你当前玩家对象是:" + sprintf("%O", user)); 95 | cecho("提示:你现在有 HP 了,可以战斗了,试试和其他生物 fight 吧。"); 96 | cecho("\n相关教程参考:https://bbs.mud.ren/threads/54\n"); 97 | cecho("提示:如果想测试玩家存档功能,使用 tutorial 5 试试吧。"); 98 | } 99 | else 100 | { 101 | cecho("你当前就在此状态,无需重复操作!"); 102 | } 103 | break; 104 | case "5": 105 | if (me->query_temp("step") != 5) 106 | { 107 | user = new (USER5, geteuid(me)); 108 | user->set_temp("step", 5); 109 | exec(user, me); 110 | destruct(me); 111 | cecho("恭喜,成功啦!\n"); 112 | cecho("你当前玩家对象是:" + sprintf("%O", user)); 113 | cecho("提示:你现在可以使用存档和读档功能了。"); 114 | cecho("\n相关教程参考:https://bbs.mud.ren/threads/46\n"); 115 | cecho("提示:系统暂未提供存档读档指令,你可以使用`eval`管理指令测试功能。"); 116 | cecho(" 如:eval me->save() 或 eval me->load()"); 117 | } 118 | else 119 | { 120 | cecho("你当前就在此状态,无需重复操作!"); 121 | } 122 | break; 123 | case "6": 124 | if (me->query_temp("step") != 6) 125 | { 126 | user = new (USER6, geteuid(me)); 127 | user->set_temp("step", 6); 128 | exec(user, me); 129 | destruct(me); 130 | cecho("恭喜,成功啦!\n"); 131 | cecho("你当前玩家对象是:" + sprintf("%O", user)); 132 | cecho("提示:你现在拥有更多能力了,如播放客户端的声音等。"); 133 | cecho("提示:如果你使用的是mudlet客户端,进入传送门后会听到美妙的音乐。"); 134 | } 135 | else 136 | { 137 | cecho("你当前就在此状态,无需重复操作!"); 138 | } 139 | break; 140 | 141 | default: 142 | cecho("你当前玩家对象是:" + sprintf("%O", me)); 143 | cecho("你当前所在环境是:" + file_name(environment(me))); 144 | if (arg) 145 | { 146 | cecho("你输入的 " + arg + " 不被支持,请使用 1~6。"); 147 | } 148 | 149 | break; 150 | } 151 | 152 | return 1; 153 | } 154 | -------------------------------------------------------------------------------- /cmds/cmd/update.c: -------------------------------------------------------------------------------- 1 | // 更新文件指令(重新载入对象) 2 | int main(object me, string file) 3 | { 4 | object ob, env = environment(me); 5 | 6 | if (!file) 7 | { 8 | return notify_fail("指令:update /文件路径/文件名\n例如:update /cmds/shutdown \n"); 9 | } 10 | 11 | if (file == "here") 12 | { 13 | if (env) 14 | file = file_name(env); 15 | else 16 | return notify_fail("你不在任何环境中。\n"); 17 | } 18 | 19 | if (file == VOID_OB) 20 | { 21 | return notify_fail("你不能在 VOID_OB 里编译 VOID_OB。\n"); 22 | } 23 | 24 | write("编译[" + file + "]:"); 25 | 26 | if (ob = find_object(file)) 27 | { 28 | destruct(ob); 29 | } 30 | 31 | if (objectp(load_object(file))) 32 | { 33 | write("成功!\n"); 34 | } 35 | else 36 | { 37 | write("失败,对象不存在!\n"); 38 | } 39 | 40 | return 1; 41 | } 42 | -------------------------------------------------------------------------------- /cmds/cmd/variables.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright: 2020, Mud.Ren 3 | File name: variables.c 4 | Description: 管理员专用,显示指定对象所有全局变量的值 5 | Author: xuefeng 6 | *****************************************************************************/ 7 | inherit CLEAN_UP; 8 | 9 | int main(object me, string arg) 10 | { 11 | object ob, env; 12 | string *vars, id; 13 | 14 | if (!arg || arg == "me" || arg == "") 15 | ob = me; 16 | else if (arg == "here") 17 | ob = environment(me); 18 | else if (sscanf(arg, "%s in %s", arg, id) == 2) 19 | { 20 | env = present(id, environment(me)); 21 | if (!env) 22 | env = present(id, me); 23 | if (!env) 24 | return notify_fail("当前环境中无法找到对象 " + id + "。\n"); 25 | if (!ob = present(arg, env)) 26 | return notify_fail("环境对象 " + id + " 中没有找到对象 " + arg + "。\n"); 27 | } 28 | else 29 | { 30 | ob = present(arg, environment(me)); 31 | if (!ob) 32 | ob = find_player(arg); 33 | if (!ob) 34 | ob = find_living(arg); 35 | if (!ob) 36 | ob = present(arg, me); 37 | if (!ob) 38 | ob = load_object(arg); 39 | if (!ob) 40 | return notify_fail("无法找到对象 " + arg + "。\n"); 41 | } 42 | if (sizeof(vars = variables(ob, 1))) 43 | foreach (string *var in vars) 44 | if (strsrch(var[1], "private") == -1) 45 | printf("%s = %O\n", var[0], fetch_variable(var[0], ob)); 46 | else 47 | printf("%s 是 %s 类型变量\n", var[0], var[1]); 48 | else 49 | return notify_fail("对象未声明任何全局变量。\n"); 50 | 51 | return 1; 52 | } 53 | 54 | int help() 55 | { 56 | write(@LONG 57 | 指令格式: variables 玩家|here|me|对象文件 58 | 指令说明: 59 | 此命令让你可以查看指定对象的详细全局变量资料。 60 | LONG ); 61 | return 1; 62 | } 63 | -------------------------------------------------------------------------------- /cmds/cmd/wizard.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | function f; 4 | 5 | if (wizardp(me)) 6 | { 7 | f = bind((: disable_wizard :), me); 8 | cecho("关闭wizard权限!"); 9 | } 10 | else 11 | { 12 | f = bind((: enable_wizard :), me); 13 | cecho("开启wizard权限!"); 14 | } 15 | evaluate(f); 16 | 17 | return 1; 18 | } 19 | -------------------------------------------------------------------------------- /cmds/demo/2.1.1.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.1 2 | int main(object me, string arg) 3 | { 4 | #ifdef FLUFFOS 5 | // MAX_INT、MIN_INT 为 fluffos 定义宏 6 | int a = MAX_INT, b = MIN_INT; 7 | // 赋值时做运算 8 | int c = MAX_INT + 1, d = MIN_INT - 1, e = d - 1; 9 | // 赋值超出取值范围(10倍) 10 | int f = 92233720368547758070, g = -92233720368547758080; 11 | // 输出 12 | printf("a = % d\nb = % d\nc = % d\nd = % d\ne = % d\nf = % d\ng = % d\n", a, b, c, d, e, f, g); 13 | #endif 14 | return 1; 15 | } 16 | -------------------------------------------------------------------------------- /cmds/demo/2.1.2.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.2 2 | int main(object me, string arg) 3 | { 4 | int a = 16, b = 'a', c = 0xF; 5 | 6 | printf("a 十进制为%d,八进制为%o,十六进制为%x\n", a, a, a); 7 | printf("b 十进制为%d,ASCII字符为%c\n", b, b); 8 | printf("c 十进制为%d,十六进制为%x或%X\n", c, c, c); 9 | 10 | return 1; 11 | } 12 | -------------------------------------------------------------------------------- /cmds/demo/2.1.3.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.3 2 | int main(object me, string arg) 3 | { 4 | #ifdef FLUFFOS 5 | float fa = MAX_FLOAT; 6 | // 最小值 7 | float f0 = MIN_FLOAT; 8 | float fi = -1 * fa; 9 | 10 | printf("fa = %f\nf0 = %f\nfi = %f\n", fa, f0, fi); 11 | #endif 12 | return 1; 13 | } 14 | -------------------------------------------------------------------------------- /cmds/demo/2.1.4.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.4 2 | int main(object me, string arg) 3 | { 4 | string s = "www.mud.ren"; 5 | printf("s = %s\n", s); 6 | 7 | return 1; 8 | } 9 | -------------------------------------------------------------------------------- /cmds/demo/2.1.5.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.5 2 | int main(object me, string arg) 3 | { 4 | #ifdef FLUFFOS 5 | string qr = " 6 | █████████████████████████████████████ 7 | █████████████████████████████████████ 8 | ████ ▄▄▄▄▄ █▀▀ ██ ▀██ █▀█ ▄▄▄▄▄ ████ 9 | ████ █ █ █▄▀██▀█▀ █▄ ▀▄█ █ █ ████ 10 | ████ █▄▄▄█ █ ▄ █ █▄▀▄█ ██ █▄▄▄█ ████ 11 | ████▄▄▄▄▄▄▄█ █ ▀▄█▄█▄▀▄▀ █▄▄▄▄▄▄▄████ 12 | ████▄▄▀▄▀█▄ █▀█ ▀ ▀ ▀▀▄█▀ ▄▄▀▄▄▀████ 13 | ████▀ ▄▄▀▄█▀▀▀ ▀█▀ ▄█ ██▀ ▄▄ █████ 14 | █████ ▀██ ▄▄▀█▄ █ █▀███ ▄██▄█▄▄████ 15 | ████▀ █▄▄▀▄▄▀ █▀▄▀█ ██ ▀███ ▄ ▄████ 16 | █████▄▄▄▀▀▄ ▄▄▄█ ▀▄ ▄▀█▄ ▀ █▀█▄▀████ 17 | ████▄█▀ █▄▄█ ▄▄ █▀▀▄ ▄▀██ █▀██ ████ 18 | ████▄█▄██▄▄▄ ▀▀▀▄ ▀█▀▄▀▀ ▄▄▄ █ ▀▀████ 19 | ████ ▄▄▄▄▄ █▄▀▀▀▄▀██▀▄▀█ █▄█ ▀▀▄█████ 20 | ████ █ █ █▀▀ ▄▄███ ▀█ ▄ ▀▀ █████ 21 | ████ █▄▄▄█ █▀ ▄ █▀▄█▄ ▄█▄▄▄▄▀▄████ 22 | ████▄▄▄▄▄▄▄█▄██▄▄▄██▄▄█▄▄██▄▄██▄█████ 23 | █████████████████████████████████████ 24 | █████████████████████████████████████ 25 | 26 | 扫码加雪风微信 ^_^ 27 | "; 28 | printf("%s\n", qr); 29 | #endif 30 | return 1; 31 | } 32 | -------------------------------------------------------------------------------- /cmds/demo/2.1.6.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.6 2 | int main(object me, string arg) 3 | { 4 | string s = "www.mud.ren"; 5 | 6 | printf("s = %s\n", s); 7 | 8 | printf("s[4..4] = %s\n", s[4..4]); 9 | printf("s[4] = %c\n",s[4]); 10 | printf("s[4] = %d\n",s[4]); 11 | printf("s[<1] = %c\n", s[<1]); 12 | printf("s[<1] = %d\n", s[<1]); 13 | printf("s[4..6] = %s\n", s[4..6]); 14 | 15 | printf("s[0..20] = %s\n", s[0..20]); 16 | printf("s[7..] = %s\n", s[7..]); 17 | 18 | printf("s[4..<1] = %s\n", s[4..<1]); 19 | printf("s[<7..<5] = %s\n", s[<7..<5]); 20 | 21 | printf("s[20..30] = %s\n", s[20..30]); 22 | printf("s[1..0] = %s\n", s[1..0]); 23 | printf("s[<5..<7] = %s\n", s[<5..<7]); 24 | 25 | return 1; 26 | } 27 | -------------------------------------------------------------------------------- /cmds/demo/2.1.7.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.7 2 | int main(object me, string arg) 3 | { 4 | string *str = ({"www", "mud", "ren"}); 5 | #ifdef FLUFFOS 6 | int *arr = allocate(1 + random(9), (: $1 :)); 7 | #else 8 | int *arr = allocate(1 + random(9)); 9 | #endif 10 | // @代表参数是数组,使用除@以外的格式循环输出数组的每个元素 11 | printf("str = %@-4s\n", str); 12 | printf("str[0] = %s, str[1] = %s, str[2] = %s\n", str[0], str[1], str[2]); 13 | printf("arr = %@','-2d\n", arr); 14 | 15 | return 1; 16 | } 17 | -------------------------------------------------------------------------------- /cmds/demo/2.1.8.c: -------------------------------------------------------------------------------- 1 | // 示例:2.1.8 2 | class example { 3 | string name; 4 | int age; 5 | string *lover; 6 | } 7 | 8 | class example test(string name, int age, string *lover) 9 | { 10 | class example test = new (class example); 11 | // 赋值 12 | test->name = name; 13 | test->age = age; 14 | test->lover = lover; 15 | return test; 16 | } 17 | 18 | int main(object me, string arg) 19 | { 20 | // 变量 21 | class example instance; 22 | 23 | instance = test("mudren", 24, ({"a", "b", "c", "d", "e"})); 24 | // 取值 25 | printf("name : %s,age : %d, lover : %@-7s\n", instance->name, instance->age, instance->lover); 26 | return 1; 27 | } 28 | -------------------------------------------------------------------------------- /cmds/demo/2.2.1.c: -------------------------------------------------------------------------------- 1 | // 2.2.1.c 2 | int main(object me, string arg) 3 | { 4 | buffer bf = read_buffer("/include/globals.h", 0, 1000); 5 | buffer BF = read_buffer(__FILE__, 0, 1000); 6 | 7 | bf += BF; 8 | for (int i = 0; i < sizeof(bf); i++) 9 | { 10 | printf("%c", bf[i]); 11 | } 12 | 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmds/demo/2.4.1.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | float f = 251; 4 | int w = 19.427; 5 | int x = 92.78; 6 | int y = 0.52; 7 | int z = -87.27; 8 | 9 | printf("f = %f, w = %d, x = %d, y = %d, z = %d\n", f, w, x, y, z); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/2.5.1.c: -------------------------------------------------------------------------------- 1 | // 转义字符输出 2 | int main(object me, string arg) 3 | { 4 | // 字符串 5 | write("\61\11\62\11\63\12"); 6 | write("\141\x9\142\x9\143\xa"); 7 | write("\61\62\63\t\x61\x62\x63\n"); 8 | write("\123"); 9 | write("\n"); 10 | // 字符 11 | write('\123'); 12 | write("\n"); 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmds/demo/3.2.1.c: -------------------------------------------------------------------------------- 1 | // 示例:3.2.1 2 | int main(object me, string arg) 3 | { 4 | // 数组合并运算 5 | int *a, *b, *c; 6 | a = ({1, 2, 3}); 7 | b = ({3, 2, 1}); 8 | c = a + b; 9 | c -= ({3}); 10 | printf("c = %O\n", c); 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/3.2.2.c: -------------------------------------------------------------------------------- 1 | // 示例:3.2.2 2 | int main(object me, string arg) 3 | { 4 | // 字符串合并 5 | string str1, str2; 6 | str1 = "hello, "; 7 | str2 = "mudren!"; 8 | printf("str1 + str2 = %s\n", str1 + str2); 9 | // 字符串大小比较 10 | if (str1 > str2) 11 | { 12 | printf("str1 > str2\n"); 13 | } 14 | else 15 | { 16 | printf("str1 <= str2\n"); 17 | } 18 | 19 | return 1; 20 | } 21 | -------------------------------------------------------------------------------- /cmds/demo/3.3.1.c: -------------------------------------------------------------------------------- 1 | // 示例:3.3.1 2 | int main(object me, string arg) 3 | { 4 | // 字符常量类型转换运算 5 | float a = 'a'; 6 | printf("a = %f\n", a); 7 | // 自动转换成字符串类型 8 | printf("a = %s", a + "\n"); 9 | return 1; 10 | } 11 | -------------------------------------------------------------------------------- /cmds/demo/3.3.2.c: -------------------------------------------------------------------------------- 1 | // 示例:3.3.2 2 | int main(object me, string arg) 3 | { 4 | // 对象类型和字符串类型的数据转换 5 | object ob = this_object(); 6 | printf("当前文件:%s", file_name(ob) + "\n"); 7 | return 1; 8 | } 9 | -------------------------------------------------------------------------------- /cmds/demo/4.1.1.c: -------------------------------------------------------------------------------- 1 | // 示例:4.1.1 2 | int main(object me, string arg) 3 | { 4 | switch(arg) 5 | { 6 | case "mud": 7 | printf("mud.ren:5555\n"); 8 | break; 9 | case "bbs": 10 | printf("bbs.mud.ren\n"); 11 | break; 12 | case "wiki": 13 | printf("mud.wiki\n"); 14 | break; 15 | default: 16 | printf("www.mud.ren\n"); 17 | } 18 | 19 | return 1; 20 | } 21 | -------------------------------------------------------------------------------- /cmds/demo/4.2.1.c: -------------------------------------------------------------------------------- 1 | // 示例:4.2.1 2 | int main(object me, string arg) 3 | { 4 | int *array = ({1, 2, 3, 4, 5, 6, 7}); 5 | 6 | foreach(int i in array) 7 | { 8 | printf("%d\n", i); 9 | } 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/5.1.1.c: -------------------------------------------------------------------------------- 1 | // 示例:5.1.1 2 | // apply 方法,对象加载时自动执行 3 | void create() 4 | { 5 | // 发送信息给当前玩家 6 | write("create 5.1.1!\n"); 7 | } 8 | 9 | // apply 方法,设置心跳后自动执行 10 | void heart_beat() 11 | { 12 | // 记录日志,请在driver界面或 debug.log 文件中查看 13 | debug_message(file_name(this_object()) + ": " + time()); 14 | } 15 | 16 | int main(object me, string arg) 17 | { 18 | if (query_heart_beat()) 19 | { 20 | write("停止心跳!\n"); 21 | set_heart_beat(0); 22 | } 23 | else 24 | { 25 | write("开始心跳!\n"); 26 | set_heart_beat(1); 27 | } 28 | 29 | return 1; 30 | } 31 | -------------------------------------------------------------------------------- /cmds/demo/5.2.1.c: -------------------------------------------------------------------------------- 1 | // 示例:5.2.1 2 | 3 | // 全局变量,可以在当前文件中使用,不会被存档 4 | nosave string file = "/data/dbase"; 5 | // 全局变量,可以在当前文件中使用,会被存档 6 | string data; 7 | 8 | int sum(int m, int n); 9 | 10 | int main(object me, string arg) 11 | { 12 | // me、arg 是局部变量,可以在 main() 内部使用 13 | if (arg == "load") 14 | { 15 | if (file_size(file + __SAVE_EXTENSION__) > 0) 16 | { 17 | // 读取存档,file 是全局变量 18 | restore_object(file); 19 | printf("data = %s\n", data); 20 | } 21 | else 22 | { 23 | printf("目前没有存档!\n"); 24 | } 25 | } 26 | else if (arg) 27 | { 28 | // data 是全局变量 29 | data = arg; 30 | // 数据存档,file 是全局变量 31 | if (!catch (save_object(file))) 32 | { 33 | printf("数据存档成功!\n"); 34 | } 35 | else 36 | { 37 | printf("数据存档失败,请确认存档目录 data 存在!\n"); 38 | } 39 | } 40 | else 41 | { 42 | // begin、end、result 是块级变量,只能在本代码块内使用 43 | int begin = 1, end = 1024; 44 | int result = sum(begin, end); 45 | printf("The sum from %d to %d is %d\n", begin, end, result); 46 | } 47 | 48 | return 1; 49 | } 50 | 51 | int sum(int m, int n) 52 | { 53 | int sum = 0; 54 | //m、n、sum 都是局部变量,只能在 sum() 内部使用 55 | // i 是块级变量,只能在 for 循环内部使用 56 | for (int i = m; i <= n; i++) 57 | { 58 | sum += i; 59 | } 60 | return sum; 61 | } 62 | -------------------------------------------------------------------------------- /cmds/demo/5.3.1.c: -------------------------------------------------------------------------------- 1 | // 示例:5.3.1.c 2 | int main(object me, string arg) 3 | { 4 | // 移动当前对象到指令 test 中 5 | move_object("/cmds/test/test"); 6 | 7 | printf("当前对象所在环境:%O\n", environment()); 8 | printf("当前玩家所在环境:%O\n", environment(me)); 9 | 10 | // 移动当前对象到当前玩家所在环境中 11 | move_object(environment(me)); 12 | 13 | printf("当前对象所在环境的所有对象:\n"); 14 | foreach (object ob in all_inventory(environment())) 15 | { 16 | printf(" - %O\n", ob); 17 | } 18 | printf("当前对象所在环境中的第一个对象:%O\n", first_inventory(environment())); 19 | printf("当前对象所在环境的下一个对象:%O\n", next_inventory()); 20 | 21 | // 移动当前对象到当前玩家中 22 | move_object(me); 23 | 24 | printf("当前玩家所在环境的所有对象:\n"); 25 | foreach (object ob in all_inventory(environment(me))) 26 | { 27 | printf(" - %O\n", ob); 28 | } 29 | printf("当前玩家中的所有对象:\n"); 30 | foreach (object ob in all_inventory(me)) 31 | { 32 | printf(" - %O\n", ob); 33 | } 34 | printf("当前玩家所在环境的所有对象(包括玩家中的对象):\n"); 35 | foreach (object ob in deep_inventory(environment(me))) 36 | { 37 | printf(" - %O\n", ob); 38 | } 39 | printf("当前对象所在环境:%O\n", environment()); 40 | 41 | return 1; 42 | } 43 | -------------------------------------------------------------------------------- /cmds/demo/5.4.1.c: -------------------------------------------------------------------------------- 1 | // 示例:5.4.1.c 2 | void input(string arg) 3 | { 4 | if (!arg || arg == "") 5 | { 6 | write("内容不能为空,请重新输入:"); 7 | input_to("input"); 8 | } 9 | else 10 | { 11 | write("你输入的内容是:" + arg + "\n"); 12 | write("请输入英文字符:"); 13 | get_char("getchar"); 14 | } 15 | } 16 | 17 | void getchar(string arg) 18 | { 19 | // 注意,这里还应该加上非英文字符判断,否则获取的可能不是你期望的 20 | if (!arg || arg == "") 21 | { 22 | write("字符不能为空,请重新输入:"); 23 | input_to("getchar"); 24 | } 25 | else 26 | { 27 | write("你输入的字符是:" + arg + "\n"); 28 | } 29 | } 30 | 31 | int main(object me, string arg) 32 | { 33 | write("请输入内容:"); 34 | input_to("input"); 35 | 36 | return 1; 37 | } 38 | -------------------------------------------------------------------------------- /cmds/demo/5.7.1.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.1 2 | int main(object me, string arg) 3 | { 4 | // 取得游戏中所有已加载对象 5 | object *obs = objects(); 6 | 7 | // 输出对象数组中的对象 8 | printf("%O\n", obs); 9 | 10 | return 1; 11 | } 12 | -------------------------------------------------------------------------------- /cmds/demo/5.7.2.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.2 2 | int main(object me, string arg) 3 | { 4 | // 复制 test 对象 5 | object new_ob = new("/cmds/test/test"); 6 | 7 | // 取得游戏中所有已加载的复制对象 8 | object *obs = objects((:clonep:)); 9 | 10 | printf("%O\n", obs); 11 | printf("new_ob = %O\n", new_ob); 12 | 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmds/demo/5.7.3.1.c: -------------------------------------------------------------------------------- 1 | inherit "/cmds/demo/5.7.3"; 2 | -------------------------------------------------------------------------------- /cmds/demo/5.7.3.2.c: -------------------------------------------------------------------------------- 1 | inherit "/cmds/demo/5.7.3.1"; 2 | -------------------------------------------------------------------------------- /cmds/demo/5.7.3.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.3 2 | 3 | int main(object me, string arg) 4 | { 5 | cecho("我是示例 5.7.3!"); 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/demo/5.7.4.1.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.4.1 2 | string s1 = "我在示例 5.7.4.1 中!"; 3 | 4 | void test1() 5 | { 6 | cecho(s1); 7 | } 8 | -------------------------------------------------------------------------------- /cmds/demo/5.7.4.2.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.4.2 2 | string s2 = "我在示例 5.7.4.2 中!"; 3 | 4 | void test2() 5 | { 6 | cecho(s2); 7 | } 8 | -------------------------------------------------------------------------------- /cmds/demo/5.7.4.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.4 2 | inherit "/cmds/demo/5.7.4.1"; 3 | inherit "/cmds/demo/5.7.4.2"; 4 | 5 | int main(object me, string arg) 6 | { 7 | // 直接调用继承对象中的方法 8 | test1(); 9 | test2(); 10 | // 直接使用继承对象的全局变量 11 | cecho(s1); 12 | cecho(s2); 13 | 14 | return 1; 15 | } 16 | -------------------------------------------------------------------------------- /cmds/demo/5.7.5.1.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.5.1 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob = load_object("/cmds/demo/5.7.5"); 6 | 7 | ob->test1(); // 无效 8 | ob->test2(); // 无效 9 | ob->test3(); 10 | ob->test(); 11 | // 使用封装的方法修改值 12 | ob->set_s1("5.7.5.1 重新设置 private 变量的值"); 13 | // 通地封装的方法获取值 14 | cecho(ob->get_s1()); 15 | return ob->main(); 16 | } 17 | -------------------------------------------------------------------------------- /cmds/demo/5.7.5.2.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.5.2 2 | inherit "/cmds/demo/5.7.5"; 3 | 4 | int main(object me, string arg) 5 | { 6 | cecho("直接继承变量!"); 7 | cecho(s2); 8 | cecho(s3); 9 | cecho("直接继承方法!"); 10 | test2(); 11 | test3(); 12 | // 可以修改变量的值 13 | set_s1("我是 5.7.5.2 通过方法修改的 s1"); 14 | s2 = "我是 5.7.5.2 直接修改 s2"; 15 | s3 = "我是 5.7.5.2 直接修改 s3"; 16 | test(); 17 | 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /cmds/demo/5.7.5.3.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.5.3 2 | inherit "/cmds/demo/5.7.5"; 3 | 4 | int main(object me, string arg) 5 | { 6 | cecho("示例5.7.5.3"); 7 | 8 | s2 = "我是示例5.7.5.3 的 protected 类型变量"; 9 | s3 = "我是示例5.7.5.3 的 public 类型变量"; 10 | 11 | ::main(me, arg); 12 | 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmds/demo/5.7.5.4.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.5.4 2 | inherit "/cmds/demo/5.7.5.2"; 3 | inherit "/cmds/demo/5.7.5.3"; 4 | -------------------------------------------------------------------------------- /cmds/demo/5.7.5.c: -------------------------------------------------------------------------------- 1 | // 示例:5.7.5 2 | private string s1; 3 | protected string s2; 4 | public string s3; 5 | 6 | void create() 7 | { 8 | s1 = "我是示例5.7.5 的 private 类型变量"; 9 | s2 = "我是示例5.7.5 的 protected 类型变量"; 10 | s3 = "我是示例5.7.5 的 public 类型变量"; 11 | } 12 | 13 | private void test1() 14 | { 15 | cecho("调用 test1 方法"); 16 | cecho("我是示例5.7.5 的 private 类型函数"); 17 | } 18 | 19 | protected void test2() 20 | { 21 | cecho("调用 test2 方法"); 22 | cecho("我是示例5.7.5 的 protected 类型函数"); 23 | } 24 | 25 | public void test3() 26 | { 27 | cecho("调用 test3 方法"); 28 | cecho("我是示例5.7.5 的 public 类型函数"); 29 | } 30 | 31 | void test() 32 | { 33 | cecho("调用 test 方法"); 34 | cecho(s1); 35 | cecho(s2); 36 | cecho(s3); 37 | } 38 | 39 | int main(object me, string arg) 40 | { 41 | cecho("调用 main 方法"); 42 | test(); 43 | test1(); 44 | test2(); 45 | test3(); 46 | 47 | return 1; 48 | } 49 | 50 | void set_s1(string s) 51 | { 52 | s1 = s; 53 | } 54 | 55 | string get_s1() 56 | { 57 | return s1; 58 | } 59 | -------------------------------------------------------------------------------- /cmds/demo/6.2.1.c: -------------------------------------------------------------------------------- 1 | // 示例:6.2.1 2 | 3 | int main(object me, string arg) 4 | { 5 | int *a, *b = ({1}); 6 | a = b; 7 | a[0] = 2; 8 | printf("a = %O\nb = %O\n", a, b); 9 | 10 | return 1; 11 | } 12 | -------------------------------------------------------------------------------- /cmds/demo/6.2.2.c: -------------------------------------------------------------------------------- 1 | // 示例:6.2.2 2 | 3 | int main(object me, string arg) 4 | { 5 | int *a, *b = ({1}); 6 | a = copy(b); 7 | a[0] = 2; 8 | printf("a = %O\nb = %O\n", a, b); 9 | 10 | return 1; 11 | } 12 | -------------------------------------------------------------------------------- /cmds/demo/6.2.3.c: -------------------------------------------------------------------------------- 1 | // 示例:6.2.3 2 | 3 | int main(object me, string arg) 4 | { 5 | int *a, *b = ({1}); 6 | a = b; 7 | a[0] = 2; 8 | b += a; 9 | b -= a; 10 | printf("a = %O\nb = %O\n", a, b); 11 | 12 | return 1; 13 | } 14 | -------------------------------------------------------------------------------- /cmds/demo/6.3.1.c: -------------------------------------------------------------------------------- 1 | // 示例:6.3.1 2 | 3 | int main(object me, string arg) 4 | { 5 | mapping x = ([ 6 | "key1":(["test":"value1"]) 7 | ]); 8 | mapping y = ([ 9 | "key2":"value2" 10 | ]); 11 | 12 | x += y; 13 | printf("x = %O\n", x); 14 | cecho(x["test"]); 15 | cecho(x["key1"]["test"]); 16 | y *= (["value2":({1, 2, 3, 4, 5})]); 17 | printf("y = %O\n", y); 18 | 19 | return 1; 20 | } 21 | -------------------------------------------------------------------------------- /cmds/demo/6.3.2.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | // 声明映射变量 4 | mapping m1, m2, m3, m; 5 | string *keys = ({"a", "b", "c"}); 6 | // 初始化 7 | m = (["name":"mudren", "age":18, "gender":"男性"]); 8 | printf("m = %O\n", m); 9 | // 写 10 | m["name"] = "雪风"; 11 | // 增 12 | m["title"] = "MUD游戏菜鸟"; 13 | // m += (["title":"MUD游戏老鸟"]); 14 | m += (["data":([ 15 | "hp":100, 16 | "mp":50, 17 | "str":50, 18 | "def":30, 19 | "dex":20])]); 20 | m += (["ob": me]); 21 | printf("m = %O\n", m); 22 | // 删 23 | map_delete(m, "gender"); 24 | map_delete(m["data"], "mp"); 25 | // 读 26 | printf("m = %O\n", m); 27 | printf("name = %O\n", m["name"]); 28 | printf("hp = %O\n", m["data"]["hp"]); 29 | 30 | // 取所有键值 31 | printf("keys = %O\n", keys(m)); 32 | printf("values = %O\n", values(m)); 33 | 34 | // 判断 undefinedp() 35 | printf("%d\n", undefinedp(m["age"])); 36 | printf("%d\n", nullp(m["gender"])); 37 | printf("%O\n", m["gender"]); 38 | 39 | // 映射与json转换(sefun) 40 | printf("%s\n", json_encode(m)); 41 | 42 | // 初始化空映射 43 | m = allocate_mapping(100); 44 | printf("m = %O\n", m); 45 | m = ([]); 46 | printf("m = %O\n", m); 47 | 48 | m1 = allocate_mapping(keys, ({"一", "二", "三"})); 49 | m2 = allocate_mapping(keys, "mud"); 50 | m3 = allocate_mapping(keys, (: repeat_string($1, 5) :)); 51 | printf("m1 = %O\n", m1); 52 | printf("m2 = %O\n", m2); 53 | printf("m3 = %O\n", m3); 54 | 55 | // 运算 56 | m1 = ([]); 57 | m2 = ([]); 58 | m1["driver"] = "mudos"; 59 | m2["mudos"] = "fluffos"; 60 | m3 = m1 + m2; 61 | printf("m3 = %O\n", m3); 62 | m3 = m1 * m2; 63 | printf("m3 = %O\n", m3); 64 | 65 | // copy 66 | m2 = m1; 67 | m3 = copy(m1); 68 | printf("m1 = %O\n", m1); 69 | m2["mudos"] = "fluffos"; 70 | printf("m1 = %O\n", m1); 71 | printf("m3 = %O\n", m3); 72 | 73 | // 关于映射中的键 74 | m[0] = "test"; 75 | m[me] = "test"; 76 | m[keys] = "test"; 77 | printf("m = %O\n", m); 78 | 79 | return 1; 80 | } 81 | -------------------------------------------------------------------------------- /cmds/demo/6.4.1.c: -------------------------------------------------------------------------------- 1 | // 示例:6.4.1 2 | int main(object me, string arg) 3 | { 4 | string qr = @EOF 5 | █████████████████████████████████████ 6 | █████████████████████████████████████ 7 | ████ ▄▄▄▄▄ █▀█ █▄▄▄▀ ██▄ █ ▄▄▄▄▄ ████ 8 | ████ █ █ █▀▀▀█ ▀ ▀█▀▄ ▄█ █ █ ████ 9 | ████ █▄▄▄█ █▀ █▀▀ ▀▀ ▀▀▄▀█ █▄▄▄█ ████ 10 | ████▄▄▄▄▄▄▄█▄▀ ▀▄█ █▄█▄█ █▄▄▄▄▄▄▄████ 11 | ████▄ ▄ █▄ ▄▀▄▀▄ █▀ █ ▀ ▀ ▀▄█▄▀████ 12 | ████▀█▀▄█▀▄▀██▄█▀██ █ ▀ ▀▄▄ ▀█▀█████ 13 | ████▀▀▀▄▄▀▄▄ ▄▄█▄▄ ▄ ▄▄ ▀▀▀▀▀▄▄█▀████ 14 | ████▀▄ ▄ ▄█ █▄ ▄█▄▄██ ▀▄▄▄▀█▄▄▀█████ 15 | ████ ▄▀▄▄▀▄▀ ▀▀▄ ▄▄▄▄ ▄▀▀█▀█▀▄ █▀████ 16 | ████ █▄█▄ ▄▀▄█▀▀ █▀ ██▄▀▀ ██▀█▄▀█████ 17 | ████▄█▄▄▄█▄█ ▀ ▄ ▄█▀▄▄▄ ▄▄▄ ▀ ████ 18 | ████ ▄▄▄▄▄ █▄█▄█▀██▄▀▄█▄ █▄█ ▄▄▀▀████ 19 | ████ █ █ █ ▄ ▀▀ ▄▄ ▄▄▀▄▄▄ ▄▀ ▀ ████ 20 | ████ █▄▄▄█ █ █▄▀ █▄ ██▀ ▄ ▄ █████ 21 | ████▄▄▄▄▄▄▄█▄▄▄██▄█▄▄▄▄▄████▄▄▄██████ 22 | █████████████████████████████████████ 23 | █████████████████████████████████████ 24 | 支付宝扫码打赏 25 | EOF; 26 | printf("%s\n", qr); 27 | return 1; 28 | } 29 | -------------------------------------------------------------------------------- /cmds/demo/6.4.2.c: -------------------------------------------------------------------------------- 1 | // 示例:6.4.2 2 | int main(object me, string arg) 3 | { 4 | string *arr = ({"master", "apply", "efun", "mud", "fluffos", "test"}); 5 | printf("原始数组 = %O\n", arr); 6 | printf("排序后数组 = %O\n", sort_array(arr, (: strcmp :))); 7 | return 1; 8 | } 9 | -------------------------------------------------------------------------------- /cmds/demo/7.2.1.1.c: -------------------------------------------------------------------------------- 1 | // 示例:7.2.1.1 2 | inherit __DIR__ "7.2.1"; 3 | -------------------------------------------------------------------------------- /cmds/demo/7.2.1.c: -------------------------------------------------------------------------------- 1 | // 示例:7.2.1 2 | int main(object me, string arg) 3 | { 4 | cecho("文件目录:" + __DIR__); 5 | cecho("文件名:" + __FILE__); 6 | #ifdef FLUFFOS 7 | cecho("当行前:" + __LINE__); 8 | #endif 9 | cecho("文件名:" + file_name()); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/7.2.2.c: -------------------------------------------------------------------------------- 1 | // 示例:7.2.2 2 | #define F(f) f 3 | #define STR(s) #s 4 | 5 | int main(object me, string arg) 6 | { 7 | cecho(F("mud.ren")); 8 | // 不能使用,cecho(F(mud.ren)); 会报错! 9 | #ifdef FLUFFOS 10 | cecho(STR(mud.ren)); 11 | cecho(STR("mud.ren")); 12 | #endif 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmds/demo/7.3.1.c: -------------------------------------------------------------------------------- 1 | // 示例:7.3.1 2 | #define X 11 3 | 4 | int main(object me, string arg) 5 | { 6 | #ifdef FLUFFOS 7 | cecho("driver 是 FLUFFOS!"); 8 | #else 9 | cecho("driver 是 MUDOS!"); 10 | #endif 11 | 12 | #if X < 1 || X > 10 13 | cecho("X = " + X); 14 | #else 15 | cecho("..."); 16 | #endif 17 | 18 | #ifdef __PACKAGE_DB__ 19 | cecho("支持数据库!"); 20 | #endif 21 | 22 | return 1; 23 | } 24 | -------------------------------------------------------------------------------- /cmds/demo/8.2.1.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | #ifdef __PACKAGE_DB__ 4 | #ifndef __USE_SQLITE3__ 5 | cecho("当前驱动不支持SQLITE3数据库。"); 6 | #else 7 | mixed db, err; 8 | 9 | if (!arg) 10 | return notify_fail(db_status()); 11 | 12 | if (arg == "db_connect") 13 | { 14 | db = db_connect("", "/tmp/sqlite.db", "", __USE_SQLITE3__); 15 | if (stringp(db)) /* error */ 16 | cecho("数据库连接失败:" + db); 17 | else 18 | cecho("数据库连接成功:" + db); 19 | } 20 | else 21 | { 22 | err = catch(db = db_close(atoi(arg))); 23 | if (stringp(err)) /* error */ 24 | cecho("数据库关闭出错:" + err); 25 | else if (db) 26 | cecho("数据库关闭成功!"); 27 | else 28 | cecho("数据库关闭失败!"); 29 | } 30 | #endif 31 | #else 32 | cecho("当前驱动不支持数据库。"); 33 | #endif 34 | return 1; 35 | } 36 | -------------------------------------------------------------------------------- /cmds/demo/8.2.2.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | #ifdef __PACKAGE_DB__ 4 | #ifndef __USE_SQLITE3__ 5 | cecho("当前驱动不支持SQLITE3数据库。"); 6 | #else 7 | mixed db, rows, *res; 8 | 9 | db = db_connect("", "/tmp/sqlite.db", "", __USE_SQLITE3__); 10 | if (stringp(db)) /* error */ 11 | cecho("数据库连接失败:" + db); 12 | else 13 | { 14 | rows = db_exec(db, "DROP TABLE IF EXISTS demo"); 15 | rows = db_exec(db, "create table IF NOT EXISTS demo(name varchar(10), value bigint);"); 16 | rows = db_exec(db, "insert into demo values('hello!',10);"); 17 | rows = db_exec(db, "insert into demo values('goodbye', 20);"); 18 | rows = db_exec(db, "insert into demo values('largeint', 9223372036854775807);"); 19 | rows = db_exec(db, "select * from demo;"); 20 | 21 | for (int i = 0; i <= rows; i++) 22 | { 23 | res = db_fetch(db, i); 24 | // printf("%O\n", res); 25 | cecho(res[0] + " " + res[1]); 26 | } 27 | 28 | db_close(db); 29 | } 30 | #endif 31 | #else 32 | cecho("当前驱动不支持数据库。"); 33 | #endif 34 | return 1; 35 | } 36 | -------------------------------------------------------------------------------- /cmds/demo/8.3.6.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define STREAM 1 4 | #define EESUCCESS 1 5 | 6 | nosave mapping status = ([]); 7 | nosave object receiver; 8 | 9 | void write_data(int fd) 10 | { 11 | socket_write(fd, "GET " + status[fd]["path"] + " HTTP/1.1\nHost: " + status[fd]["host"] + "\n\r\n\r"); 12 | } 13 | 14 | void receive_data(int fd, mixed result) 15 | { 16 | string idiom; 17 | result = result[strsrch(result, "{")..]; 18 | // debug_message(sprintf("%d || %O", strlen(result), result)); 19 | if (strsrch(result, "total") > -1) 20 | { 21 | int total; 22 | result = json_decode(result); 23 | total = result["total"]; 24 | idiom = HIY "和 " + status[fd]["keyword"] + " 相关的成语共有 " + total + " 条,索引如下:" NOR + "\n"; 25 | result = result["result"]; 26 | idiom += "----------------------------------------\n"; 27 | foreach (mapping list in result) 28 | { 29 | idiom += HIC "成语:" + list["name"] + "\n索引:" + list["id"] + NOR + "\n"; 30 | } 31 | idiom += "----------------------------------------\n"; 32 | 33 | if (total > 20) 34 | { 35 | idiom += HIR "相关成语超过二十条,推荐使用更精确的关键词查询。" NOR "\n"; 36 | } 37 | 38 | idiom += HIG "可以使用 `8.3.6 索引` 阅读指定成语。" NOR "\n"; 39 | 40 | tell_object(receiver, idiom); 41 | } 42 | else 43 | { 44 | result = json_decode(result); 45 | if (result["error_code"]) 46 | { 47 | tell_object(receiver, "没有找到相关索引成语。\n"); 48 | } 49 | else 50 | { 51 | result = result["result"]; 52 | idiom = "----------------------------------------\n"; 53 | idiom += HIY "成语:" + result["name"] + NOR "\n"; 54 | idiom += HIW "读音:" + result["spell"] + NOR + "\n"; 55 | idiom += "----------------------------------------\n"; 56 | idiom += HIC "解释:" + result["content"] + NOR + "\n"; 57 | if (result["derivation"]) 58 | { 59 | idiom += HIW "出处:" + result["derivation"] + NOR + "\n"; 60 | } 61 | if (result["samples"]) 62 | { 63 | idiom += HIW "示例:" + result["samples"] + NOR + "\n"; 64 | } 65 | idiom += "----------------------------------------\n"; 66 | tell_object(receiver, idiom); 67 | } 68 | } 69 | } 70 | 71 | void receive_callback(int fd, mixed result, string addr) 72 | { 73 | // 此方法无效 74 | } 75 | 76 | void socket_shutdown(int fd) 77 | { 78 | socket_close(fd); 79 | } 80 | 81 | int main(object me, string arg) 82 | { 83 | int fd; 84 | int ret; 85 | string host = "api.avatardata.cn"; 86 | string addr = "121.42.196.237 80"; 87 | string key = "f47de96f0bd04223817aca17ca150f0e"; 88 | string path; 89 | 90 | receiver = me; 91 | if (is_chinese(arg)) 92 | { 93 | path = "/ChengYu/Search?key=" + key + "&keyWord=" + arg; 94 | msg("info", "$ME开始查找和 " + arg + " 相关的成语。", receiver); 95 | } 96 | else if (strlen(arg) == 36) 97 | { 98 | path = "/ChengYu/LookUp?key=" + key + "&id=" + arg; 99 | msg("info", "$ME开始查阅成语的详细解释。", receiver); 100 | } 101 | else 102 | { 103 | path = "/ChengYu/Random?key=" + key; 104 | msg("info", "$ME开始学习成语。", receiver); 105 | } 106 | 107 | fd = socket_create(STREAM, "receive_callback", "socket_shutdown"); 108 | status[fd] = ([]); 109 | status[fd]["host"] = host; 110 | status[fd]["path"] = path; 111 | status[fd]["keyword"] = arg; 112 | 113 | ret = socket_connect(fd, addr, "receive_data", "write_data"); 114 | if (ret != EESUCCESS) 115 | { 116 | tell_object(receiver, "服务器连接失败。\n"); 117 | socket_close(fd); 118 | } 119 | 120 | return 1; 121 | } 122 | -------------------------------------------------------------------------------- /cmds/demo/QRcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define STREAM 1 4 | #define EESUCCESS 1 5 | 6 | nosave mapping status = ([]); 7 | nosave object receiver; 8 | 9 | void write_data(int fd) 10 | { 11 | socket_write(fd, "GET " + status[fd]["path"] + " HTTP/1.1\nHost: " + status[fd]["host"] + "\n\r\n\r"); 12 | } 13 | 14 | void receive_data(int fd, mixed result) 15 | { 16 | result = result[strsrch(result, "
") + 5..strsrch(result, "
") - 1]; 17 | // debug_message(sprintf("%d || %O", strlen(result), result)); 18 | tell_object(receiver, result); 19 | } 20 | 21 | void receive_callback(int fd, mixed result, string addr) 22 | { 23 | // 此方法无效 24 | } 25 | 26 | void socket_shutdown(int fd) 27 | { 28 | socket_close(fd); 29 | } 30 | 31 | int main(object me, string arg) 32 | { 33 | int fd; 34 | int ret; 35 | string host = "qrenco.de"; 36 | string addr = "5.9.243.188 80"; 37 | string path = "/" + arg; 38 | 39 | receiver = me; 40 | 41 | fd = socket_create(STREAM, "receive_callback", "socket_shutdown"); 42 | status[fd] = ([]); 43 | status[fd]["host"] = host; 44 | status[fd]["path"] = path; 45 | 46 | ret = socket_connect(fd, addr, "receive_data", "write_data"); 47 | if (ret != EESUCCESS) 48 | { 49 | tell_object(receiver, "服务器连接失败。\n"); 50 | socket_close(fd); 51 | } 52 | 53 | return 1; 54 | } 55 | -------------------------------------------------------------------------------- /cmds/demo/arraysort.c: -------------------------------------------------------------------------------- 1 | // 生成乱序数组 2 | int *array(int n) 3 | { 4 | if (n > 15000) 5 | { 6 | n = 15000; 7 | } 8 | 9 | // return shuffle(allocate(n, (: $1 * secure_random($(n)) :))); 10 | return shuffle(allocate(n, (: $1 + 1 :))); 11 | } 12 | 13 | // 交换数组元素 14 | void swap(int *arr, int i, int j) 15 | { 16 | int temp = arr[i]; 17 | arr[i] = arr[j]; 18 | arr[j] = temp; 19 | } 20 | 21 | /* 22 | * 冒泡排序 23 | */ 24 | void bubbleSort(int *arr) 25 | { 26 | int len = sizeof(arr); 27 | for (int i = 0; i < len - 1; i++) 28 | { 29 | for (int j = 0; j < len - 1 - i; j++) 30 | { 31 | if (arr[j] > arr[j + 1]) 32 | { 33 | swap(arr, j, j + 1); 34 | } 35 | } 36 | } 37 | } 38 | 39 | /* 40 | * 快速排序 41 | */ 42 | int partition(int *arr, int left, int right) 43 | { 44 | int pivot = left, index = pivot + 1; 45 | for (int i = index; i <= right; i++) 46 | { 47 | if (arr[i] < arr[pivot]) 48 | { 49 | swap(arr, i, index); 50 | index++; 51 | } 52 | } 53 | swap(arr, pivot, index - 1); 54 | return index - 1; 55 | } 56 | 57 | varargs void quickSort(int *arr, int left, int right) 58 | { 59 | int len = sizeof(arr), index; 60 | 61 | if (nullp(right)) 62 | { 63 | right = len - 1; 64 | } 65 | 66 | if (left < right) 67 | { 68 | index = partition(arr, left, right); 69 | quickSort(arr, left, index - 1); 70 | quickSort(arr, index + 1, right); 71 | } 72 | } 73 | 74 | /* 75 | * 插入排序 76 | */ 77 | void insertionSort(int *arr) 78 | { 79 | int len = sizeof(arr), index, current; 80 | 81 | for (int i = 1; i < len; i++) 82 | { 83 | index = i - 1; 84 | current = arr[i]; 85 | while (index >= 0 && arr[index] > current) 86 | { 87 | arr[index + 1] = arr[index]; 88 | index--; 89 | } 90 | arr[index + 1] = current; 91 | } 92 | } 93 | 94 | /* 95 | * 选择排序 96 | */ 97 | void selectionSort(int *arr) 98 | { 99 | int len = sizeof(arr), index; 100 | 101 | for (int i = 0; i < len - 1; i++) 102 | { 103 | index = i; 104 | for (int j = i + 1; j < len; j++) 105 | { 106 | if (arr[j] < arr[index]) 107 | { 108 | index = j; 109 | } 110 | } 111 | swap(arr, i, index); 112 | } 113 | } 114 | 115 | /* 116 | * 归并排序 117 | */ 118 | int *merge(int *left, int *right) 119 | { 120 | int *result = ({}); 121 | 122 | while (sizeof(left) && sizeof(right)) 123 | { 124 | if (left[0]<=right[0]) 125 | { 126 | result += ({left[0]}); 127 | left -= ({left[0]}); 128 | } 129 | else 130 | { 131 | result += ({right[0]}); 132 | right -= ({right[0]}); 133 | } 134 | } 135 | while (sizeof(left)) 136 | { 137 | result += ({left[0]}); 138 | left -= ({left[0]}); 139 | } 140 | while (sizeof(right)) 141 | { 142 | result += ({right[0]}); 143 | right -= ({right[0]}); 144 | } 145 | 146 | return result; 147 | } 148 | 149 | int *mergeSort(int *arr) 150 | { 151 | int len = sizeof(arr); 152 | int middle, *left, *right; 153 | 154 | if (len < 2) 155 | { 156 | return arr; 157 | } 158 | 159 | middle = floor(len / 2); 160 | left = arr[0..middle-1]; 161 | right = arr[middle..]; 162 | 163 | return merge(mergeSort(left), mergeSort(right)); 164 | } 165 | 166 | // 排序测试 167 | int main(object me, string arg) 168 | { 169 | int n = atoi(arg); 170 | int *arr = array(n); 171 | int *arr1 = copy(arr), *arr2 = copy(arr), *arr3 = copy(arr), *arr4 = copy(arr), *arr5 = copy(arr); 172 | int t, t1, t2, t3, t4, t5; 173 | 174 | if (!n) 175 | { 176 | cecho("请输入 `arraysort n` 生成数据并测试,n 为待排序数据个数。"); 177 | return 1; 178 | } 179 | // 待排序数据 180 | printf("arr:%@ d\n", arr); 181 | t = time_expression(arr = sort_array(arr, 1)); 182 | t1 = time_expression(bubbleSort(arr1)); 183 | t2 = time_expression(quickSort(arr2)); 184 | t3 = time_expression(insertionSort(arr3)); 185 | t4 = time_expression(selectionSort(arr4)); 186 | t5 = time_expression(arr5 = mergeSort(arr5)); 187 | // 排序结果 188 | printf("arr0:%@ d\n", arr); 189 | printf("arr1:%@ d\n", arr1); 190 | printf("arr2:%@ d\n", arr2); 191 | printf("arr3:%@ d\n", arr3); 192 | printf("arr4:%@ d\n", arr4); 193 | printf("arr5:%@ d\n", arr5); 194 | printf("sort_array用时:%d,冒泡排序用时:%d,快速排序用时:%d,插入排序用时:%d,选择排序用时:%d,归并排序用时:%d\n", t, t1, t2, t3, t4, t5); 195 | return 1; 196 | } 197 | -------------------------------------------------------------------------------- /cmds/demo/bubblesort.c: -------------------------------------------------------------------------------- 1 | inherit __DIR__ "arraysort"; 2 | 3 | int main(object me, string arg) 4 | { 5 | int t, *arr = array(atoi(arg)); 6 | printf("待排序数据:%O", arr); 7 | // printf("已排序数据:%O", sort_array(arr, 1)); 8 | t = time_expression(bubbleSort(arr)); 9 | printf("排序结果:%O,排序用时:%d\n", arr, t); 10 | return 1; 11 | } 12 | -------------------------------------------------------------------------------- /cmds/demo/insertionsort.c: -------------------------------------------------------------------------------- 1 | inherit __DIR__ "arraysort"; 2 | 3 | int main(object me, string arg) 4 | { 5 | int t, *arr = array(atoi(arg)); 6 | printf("待排序数据:%O", arr); 7 | // printf("已排序数据:%O", sort_array(arr, 1)); 8 | t = time_expression(insertionSort(arr)); 9 | printf("排序结果:%O,排序用时:%d\n", arr, t); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/mergesort.c: -------------------------------------------------------------------------------- 1 | inherit __DIR__ "arraysort"; 2 | 3 | int main(object me, string arg) 4 | { 5 | int t, *arr = array(atoi(arg)); 6 | printf("待排序数据:%O", arr); 7 | // printf("已排序数据:%O", sort_array(arr, 1)); 8 | t = time_expression(arr = mergeSort(arr)); 9 | printf("排序结果:%O,排序用时:%d\n", arr, t); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/quicksort.c: -------------------------------------------------------------------------------- 1 | inherit __DIR__ "arraysort"; 2 | 3 | int main(object me, string arg) 4 | { 5 | int t, *arr = array(atoi(arg)); 6 | printf("待排序数据:%O", arr); 7 | // printf("已排序数据:%O", sort_array(arr, 1)); 8 | t = time_expression(quickSort(arr)); 9 | printf("排序结果:%O,排序用时:%d\n", arr, t); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/selectionsort.c: -------------------------------------------------------------------------------- 1 | inherit __DIR__ "arraysort"; 2 | 3 | int main(object me, string arg) 4 | { 5 | int t, *arr = array(atoi(arg)); 6 | printf("待排序数据:%O", arr); 7 | // printf("已排序数据:%O", sort_array(arr, 1)); 8 | t = time_expression(selectionSort(arr)); 9 | printf("排序结果:%O,排序用时:%d\n", arr, t); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/demo/socket_server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * sockets release 相关测试 3 | */ 4 | 5 | nosave int S; 6 | nosave object R; 7 | 8 | void create() 9 | { 10 | R = this_player(); 11 | } 12 | 13 | int main(object me, string arg) 14 | { 15 | if (S && arg) 16 | { 17 | int err; 18 | err = socket_write(S, arg); 19 | if (err < 0) 20 | { 21 | cecho("【Socket】socket_write error: " + socket_error(err)); 22 | } 23 | else 24 | { 25 | cecho("【Socket】消息已发送:" + arg); 26 | } 27 | } 28 | 29 | return 1; 30 | } 31 | 32 | void release_callback(int fd) 33 | { 34 | S = fd; 35 | socket_acquire(fd, "read_callback", "write_callback", "close_callback"); 36 | } 37 | 38 | void read_callback(int fd, mixed message) 39 | { 40 | tell_object(R, sprintf("【Socket】read_callback: fd = %d, message = %s\n", fd, message)); 41 | 42 | // 发送消息给客户端 43 | if (message == "hi") 44 | { 45 | socket_write(fd, "hello ^_^"); 46 | } 47 | } 48 | 49 | void write_callback(int fd) 50 | { 51 | tell_object(R, sprintf("【Socket】write_callback: fd = %d\n", fd)); 52 | } 53 | 54 | void close_callback(int fd) 55 | { 56 | tell_object(R, sprintf("【Socket】close_callback: fd = %d\n", fd)); 57 | socket_close(fd); 58 | } 59 | -------------------------------------------------------------------------------- /cmds/demo/socket_status.c: -------------------------------------------------------------------------------- 1 | // 显示 socket_status 2 | int main(object me, string arg) 3 | { 4 | #ifdef FLUFFOS 5 | if (arg) 6 | { 7 | print_r(socket_status(atoi(arg))); 8 | } 9 | else 10 | { 11 | print_r(socket_status()); 12 | } 13 | #endif 14 | return 1; 15 | } 16 | -------------------------------------------------------------------------------- /cmds/demo/socket_tcp_client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * sockets TCP模式客户端测试 3 | */ 4 | 5 | #define TCP 1 6 | #define ADDR "127.0.0.1 6000" 7 | 8 | nosave int S; 9 | nosave object R; 10 | 11 | void close_callback(int fd) 12 | { 13 | R && tell_object(R, sprintf("【TCP客户端】close_callback: fd = %d\n", fd)); 14 | socket_close(fd); 15 | } 16 | 17 | void write_callback(int fd) 18 | { 19 | R && tell_object(R, sprintf("【TCP客户端】write_callback: fd = %d\n", fd)); 20 | } 21 | 22 | void read_callback(int fd, mixed message) 23 | { 24 | R && tell_object(R, sprintf("【TCP客户端】read_callback: fd = %d, message = %s\n", fd, message)); 25 | } 26 | 27 | private void client_init() 28 | { 29 | int err; 30 | // 创建一个 efun socket 连接 31 | S = socket_create(TCP, "read_callback", "close_callback"); 32 | if (S < 0) 33 | { 34 | cecho("【TCP客户端】socket_create error : " + socket_error(S)); 35 | } 36 | else 37 | { 38 | cecho("【TCP客户端】socket_create fd = " + S); 39 | // 启动一个 socket 连接 40 | err = socket_connect(S, ADDR, "read_callback", "write_callback"); 41 | if (err < 0) 42 | { 43 | cecho("【TCP客户端】socket_connect error : " + socket_error(err)); 44 | socket_close(S); 45 | } 46 | else 47 | { 48 | cecho("【TCP客户端】socket_connect SUCCESS!"); 49 | } 50 | } 51 | } 52 | 53 | void create() 54 | { 55 | R = this_player(); 56 | client_init(); 57 | } 58 | 59 | int main(object me, string arg) 60 | { 61 | R = me; 62 | if (arg) 63 | { 64 | int err; 65 | err = socket_write(S, arg); 66 | if (err < 0) 67 | { 68 | cecho("【TCP客户端】socket_write error : " + socket_error(err)); 69 | } 70 | else 71 | { 72 | cecho("【TCP客户端】消息已发送:" + arg); 73 | } 74 | } 75 | 76 | return 1; 77 | } 78 | -------------------------------------------------------------------------------- /cmds/demo/socket_tcp_server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * sockets 相关测试,这里是TCP模式服务端 3 | */ 4 | 5 | #define TCP 1 6 | #define PORT 6000 7 | 8 | nosave int S; 9 | nosave object R; 10 | 11 | void close_callback(int fd) 12 | { 13 | R && tell_object(R, sprintf("【TCP服务端】close_callback: fd = %d\n", fd)); 14 | socket_close(fd); 15 | } 16 | 17 | void write_callback(int fd) 18 | { 19 | R && tell_object(R, sprintf("【TCP服务端】write_callback: fd = %d\n", fd)); 20 | } 21 | 22 | void read_callback(int fd, mixed message) 23 | { 24 | R && tell_object(R, sprintf("【TCP服务端】read_callback: fd = %d, message = %s\n", fd, message)); 25 | // 发送消息给客户端 26 | if (message == "hi") 27 | { 28 | socket_write(fd, "你好呀。"); 29 | } 30 | } 31 | 32 | void listen_callback(int fd) 33 | { 34 | int err; 35 | R && tell_object(R, sprintf("【TCP服务端】listen_callback: fd = %d\n", fd)); 36 | // 在一个 socket 上接受连接 37 | S = socket_accept(fd, "read_callback", "write_callback"); 38 | if (S < 0) 39 | { 40 | R && tell_object(R, sprintf("【TCP服务端】socket_accept error: %s\n", socket_error(S))); 41 | } 42 | else 43 | { 44 | R && tell_object(R, sprintf("【TCP服务端】socket_accept: fd = %d\n", S)); 45 | err = socket_write(S, "欢迎连接到服务器 mud.ren ^_^"); 46 | if (err < 0) 47 | { 48 | R && tell_object(R, sprintf("【TCP服务端】socket_write error: %s\n", socket_error(err))); 49 | } 50 | } 51 | } 52 | 53 | private void server_init() 54 | { 55 | int s, err; 56 | 57 | // 创建一个 efun socket 连接 58 | s = socket_create(TCP, "read_callback", "close_callback"); 59 | if (s < 0) 60 | { 61 | cecho("【TCP服务端】socket_create error: " + socket_error(s)); 62 | } 63 | else 64 | { 65 | cecho("【TCP服务端】socket_create: fd = " + s); 66 | // 绑定端口到 socket 连接 67 | err = socket_bind(s, PORT); 68 | if (err < 0) 69 | { 70 | cecho("【TCP服务端】socket_bind error: " + socket_error(err)); 71 | socket_close(s); 72 | } 73 | else 74 | { 75 | cecho("【TCP服务端】socket_bind SUCCESS!"); 76 | 77 | // 监听一个 socket 连接 78 | err = socket_listen(s, "listen_callback"); 79 | if (err < 0) 80 | { 81 | cecho("【TCP服务端】socket_listen error: " + socket_error(err)); 82 | socket_close(s); 83 | } 84 | else 85 | { 86 | cecho("【TCP服务端】socket_listen ON " + socket_address(s, 1)); 87 | } 88 | } 89 | } 90 | } 91 | 92 | void create() 93 | { 94 | R = this_player(); 95 | server_init(); 96 | } 97 | 98 | int release() 99 | { 100 | if(S) 101 | { 102 | int err; 103 | err = socket_release(S, load_object(__DIR__"socket_server"), "release_callback"); 104 | if (err < 0) 105 | { 106 | cecho("【TCP服务端】socket_release error: " + socket_error(err)); 107 | } 108 | else 109 | { 110 | cecho("【TCP服务端】socket_release SUCCESS!"); 111 | } 112 | } 113 | 114 | return 1; 115 | } 116 | 117 | int main(object me, string arg) 118 | { 119 | R = me; 120 | if (arg == "release") 121 | { 122 | release(); 123 | } 124 | else if (arg) 125 | { 126 | int err; 127 | 128 | err = socket_write(S, arg); 129 | if (err < 0) 130 | { 131 | cecho("【TCP服务端】socket_write error: " + socket_error(err)); 132 | } 133 | else 134 | { 135 | cecho("【TCP服务端】消息已发送:" + arg); 136 | } 137 | } 138 | 139 | return 1; 140 | } 141 | -------------------------------------------------------------------------------- /cmds/demo/socket_udp_client.c: -------------------------------------------------------------------------------- 1 | /** 2 | * sockets DATAGRAM 模式客户端测试 3 | */ 4 | 5 | #define UDP 2 6 | #define ADDR "127.0.0.1 6000" 7 | 8 | nosave int S; 9 | nosave object R; 10 | 11 | void read_callback(int fd, mixed message, string addr) 12 | { 13 | R && tell_object(R, sprintf("【UDP客户端】read_callback: fd = %d, from = %s, message = %s\n", fd, addr, message)); 14 | } 15 | 16 | private void client_init() 17 | { 18 | // 创建一个 efun socket 连接 19 | S = socket_create(UDP, "read_callback"); 20 | // 如果不绑定端口,将使用随机端口连接服务器,但无法收到服务端返回的消息 21 | socket_bind(S, 52099); 22 | if (S < 0) 23 | { 24 | cecho("【UDP客户端】socket_create error: " + socket_error(S)); 25 | } 26 | else 27 | { 28 | cecho("【UDP客户端】socket_create: fd = " + S); 29 | } 30 | } 31 | 32 | void create() 33 | { 34 | R = this_player(); 35 | client_init(); 36 | } 37 | 38 | int main(object me, string arg) 39 | { 40 | R = me; 41 | if (arg) 42 | { 43 | int err; 44 | // UDP 发送消息到服务器 45 | err = socket_write(S, arg, ADDR); 46 | if (err < 0) 47 | { 48 | cecho("【UDP客户端】socket_write error: " + socket_error(err)); 49 | // socket_close(S); 50 | } 51 | else 52 | { 53 | cecho("【UDP客户端】消息已发送:" + arg); 54 | } 55 | } 56 | 57 | return 1; 58 | } 59 | -------------------------------------------------------------------------------- /cmds/demo/socket_udp_server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * sockets 相关测试,这里是UDP模式服务端 3 | */ 4 | 5 | #define UDP 2 6 | #define PORT 6000 7 | 8 | nosave int S; 9 | nosave string Addr; 10 | nosave object R; 11 | 12 | // udp模式使用 13 | void read_callback(int fd, mixed message, string addr) 14 | { 15 | S = fd; 16 | Addr = addr; 17 | R && tell_object(R, sprintf("【UDP服务端】read_callback: fd = %d, from = %s, message = %s\n", fd, addr, message)); 18 | // 发送消息给客户端,需要udp客户端绑定端口 19 | if (message == "hi") 20 | { 21 | socket_write(fd, "你好,客户端!", addr); 22 | } 23 | } 24 | 25 | private void server_init() 26 | { 27 | int s, err; 28 | 29 | // 创建一个 efun socket 连接 30 | s = socket_create(UDP, "read_callback"); 31 | if (s < 0) 32 | { 33 | cecho("【UDP服务端】socket_create error: " + socket_error(s)); 34 | } 35 | else 36 | { 37 | cecho("【UDP服务端】socket_create: fd = " + s); 38 | // 绑定端口到 socket 连接 39 | err = socket_bind(s, PORT); 40 | if (err < 0) 41 | { 42 | cecho("【UDP服务端】socket_bind error: " + socket_error(err)); 43 | socket_close(s); 44 | } 45 | else 46 | { 47 | cecho("【UDP服务端】socket_bind SUCCESS!"); 48 | cecho("【UDP服务端】UDP Socket 服务已启动 : " + socket_address(s, 1)); 49 | } 50 | } 51 | } 52 | 53 | void create() 54 | { 55 | R = this_player(); 56 | server_init(); 57 | } 58 | 59 | int main(object me, string arg) 60 | { 61 | R = me; 62 | if (arg) 63 | { 64 | int err; 65 | 66 | err = socket_write(S, arg, Addr); 67 | if (err < 0) 68 | { 69 | cecho("【UDP服务端】socket_write error: " + socket_error(err)); 70 | } 71 | else 72 | { 73 | cecho("【UDP服务端】消息已发送:" + arg); 74 | } 75 | } 76 | 77 | return 1; 78 | } 79 | -------------------------------------------------------------------------------- /cmds/efun/all_inventory.c: -------------------------------------------------------------------------------- 1 | // all_inventory.c 2 | int main(object me, string arg) 3 | { 4 | object ob; 5 | 6 | if (!arg) 7 | { 8 | print_r(all_inventory(me)); 9 | } 10 | else if (ob = load_object(arg)) 11 | { 12 | print_r(all_inventory(ob)); 13 | } 14 | else 15 | { 16 | cecho("没有找到对象 " + arg); 17 | } 18 | 19 | return 1; 20 | } 21 | -------------------------------------------------------------------------------- /cmds/efun/call_other.c: -------------------------------------------------------------------------------- 1 | // call_other.c 2 | int main(object me, string arg) 3 | { 4 | object ob; 5 | string arg1, arg2, err; 6 | 7 | if (!wizardp(me)) 8 | { 9 | return 0; 10 | } 11 | 12 | if (!arg || sscanf(arg,"%s %s",arg1, arg2) != 2) 13 | { 14 | cecho("指令格式: call_other /path/target function [arg1 arg2 ...]"); 15 | } 16 | else if (ob = load_object(arg1)) 17 | { 18 | if (err = catch(call_other(ob, explode(arg2, " ")))) 19 | { 20 | cecho("运行报错啦~>详细错误信息请看日志记录<:\n" + err); 21 | } 22 | } 23 | else 24 | { 25 | cecho("没有找到对象 " + arg1); 26 | } 27 | 28 | return 1; 29 | } 30 | -------------------------------------------------------------------------------- /cmds/efun/call_out_info.c: -------------------------------------------------------------------------------- 1 | // 列出游戏所有延迟呼叫中的 call_out() 2 | int main(object me, string arg) 3 | { 4 | print_r(call_out_info()); 5 | 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/efun/children.c: -------------------------------------------------------------------------------- 1 | // children.c 2 | int main(object me, string arg) 3 | { 4 | if (!arg) 5 | { 6 | cecho("指令格式: children /path/target"); 7 | } 8 | else 9 | { 10 | print_r(children(arg)); 11 | } 12 | 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmds/efun/clear_bit.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | string str; 4 | int i, n; 5 | 6 | if (arg && sscanf(arg, "%s %d", str, n) == 2) 7 | { 8 | arg = clear_bit(str, n - 1); 9 | cecho(str); 10 | // 输出位 11 | for (i = 60; i > 0; i--) 12 | { 13 | write(test_bit(str, i - 1)); 14 | } 15 | write("\n"); 16 | cecho(arg); 17 | for (i = 60; i > 0; i--) 18 | { 19 | write(test_bit(arg, i - 1)); 20 | } 21 | write("\n"); 22 | } 23 | 24 | return 1; 25 | } 26 | -------------------------------------------------------------------------------- /cmds/efun/deep_inventory.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | 7 | if (!arg) 8 | { 9 | print_r(deep_inventory(me)); 10 | } 11 | else if (ob = load_object(arg)) 12 | { 13 | print_r(deep_inventory(ob)); 14 | } 15 | else 16 | { 17 | return notify_fail(HIR "没有找到对象 " + arg + "\n" NOR); 18 | } 19 | 20 | return 1; 21 | } 22 | -------------------------------------------------------------------------------- /cmds/efun/destruct.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | 7 | if (!arg) 8 | { 9 | destruct(this_object()); 10 | return notify_fail(HIY "指令格式: destruct /path/target\n" NOR); 11 | } 12 | else if (ob = find_object(arg)) 13 | { 14 | destruct(ob); 15 | } 16 | else 17 | { 18 | return notify_fail(HIR "没有找到对象 " + arg + "\n" NOR); 19 | } 20 | 21 | return 1; 22 | } 23 | -------------------------------------------------------------------------------- /cmds/efun/disable_commands.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | function fun; 7 | 8 | if (!arg) 9 | { 10 | return notify_fail(HIY "指令格式: disable_commands /path/target\n" NOR); 11 | } 12 | 13 | if (!(ob = load_object(arg))) 14 | { 15 | return notify_fail(HIR "没有找到对象 " + arg + "\n" NOR); 16 | } 17 | 18 | fun = bind((: disable_commands :), ob); 19 | evaluate(fun); 20 | tell_object(me, HIG "对象 " + arg + " 成为非生物对象。\n" NOR); 21 | 22 | return 1; 23 | } 24 | -------------------------------------------------------------------------------- /cmds/efun/ed.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | if (query_ip_number(me) != "127.0.0.1") 6 | { 7 | return 0; 8 | } 9 | if (!arg) 10 | { 11 | return notify_fail(HIR "指令格式: ed \n" NOR); 12 | } 13 | else if (file_size(arg) < 0) 14 | { 15 | return notify_fail(HIR "文件 " + arg + " 不存在\n" NOR); 16 | } 17 | else 18 | { 19 | ed(arg); 20 | } 21 | 22 | return 1; 23 | } 24 | -------------------------------------------------------------------------------- /cmds/efun/enable_commands.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | function fun; 7 | 8 | if (!arg) 9 | { 10 | return notify_fail(HIY "指令格式: enable_commands /path/target\n" NOR); 11 | } 12 | 13 | if (!(ob = load_object(arg))) 14 | { 15 | return notify_fail(HIR "没有找到对象 " + arg + "\n" NOR); 16 | } 17 | 18 | fun = bind((: enable_commands :), ob); 19 | evaluate(fun, 0); 20 | tell_object(me, HIG "对象 " + arg + " 成为生物。\n" NOR); 21 | 22 | return 1; 23 | } 24 | -------------------------------------------------------------------------------- /cmds/efun/environment.c: -------------------------------------------------------------------------------- 1 | // environment.c 2 | int main(object me, string arg) 3 | { 4 | object ob, env; 5 | 6 | if (!arg) 7 | { 8 | if (env = environment(me)) 9 | { 10 | cecho("你在 " + file_name(env) + " 中"); 11 | } 12 | else 13 | { 14 | cecho("你没在任何环境中"); 15 | } 16 | } 17 | else if (ob = find_object(arg)) 18 | { 19 | if (env = environment(ob)) 20 | { 21 | cecho("对象 " + arg + " 在 " + file_name(env) + " 中"); 22 | } 23 | else 24 | { 25 | cecho("对象没在任何环境中"); 26 | } 27 | } 28 | else 29 | { 30 | cecho("没有找到对象 " + arg); 31 | } 32 | 33 | return 1; 34 | } 35 | -------------------------------------------------------------------------------- /cmds/efun/find_living.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | 7 | if (!arg) 8 | { 9 | return notify_fail(HIY "指令格式: find_living name\n" NOR); 10 | } 11 | if (ob = find_living(arg)) 12 | write(HIG + arg + " => " + file_name(ob) + "\n" NOR); 13 | else 14 | write(HIR "没有找到名字是 " + arg + " 的对象!\n" NOR); 15 | return 1; 16 | } 17 | -------------------------------------------------------------------------------- /cmds/efun/find_player.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | 7 | if (!arg) 8 | { 9 | return notify_fail(HIY "指令格式: find_player name\n" NOR); 10 | } 11 | if (ob = find_player(arg)) 12 | write(HIG + arg + " => " + file_name(ob) + "\n" NOR); 13 | else 14 | write(HIR "没有找到名字是 " + arg + " 的玩家!\n" NOR); 15 | return 1; 16 | } 17 | -------------------------------------------------------------------------------- /cmds/efun/first_inventory.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | 7 | if (!arg) 8 | { 9 | cecho(first_inventory(me)); 10 | } 11 | else if (ob = load_object(arg)) 12 | { 13 | cecho(first_inventory(ob)); 14 | } 15 | else 16 | { 17 | return notify_fail(HIR "没有找到对象 " + arg + "\n" NOR); 18 | } 19 | 20 | return 1; 21 | } 22 | -------------------------------------------------------------------------------- /cmds/efun/get_dir.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | if (arg) 6 | { 7 | if (file_size(arg) == -2) 8 | { 9 | if (arg[strlen(arg) - 1] != '/') arg += "/"; 10 | print_r(get_dir(arg)); 11 | } 12 | else if (file_size(arg) == -1) 13 | { 14 | return notify_fail(HIR "目录不存在或你无权读取。\n" NOR); 15 | } 16 | else 17 | { 18 | print_r(get_dir(arg, -1)); 19 | } 20 | } 21 | else 22 | { 23 | print_r(get_dir("/")); 24 | } 25 | 26 | return 1; 27 | } 28 | -------------------------------------------------------------------------------- /cmds/efun/heart_beats.c: -------------------------------------------------------------------------------- 1 | // 打印游戏所有有心跳的对象 2 | int main(object me, string arg) 3 | { 4 | print_r(heart_beats()); 5 | 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/efun/livings.c: -------------------------------------------------------------------------------- 1 | // 列出游戏所有活着的对象 2 | int main(object me, string arg) 3 | { 4 | print_r(livings()); 5 | 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/efun/move_object.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | string msg, str1, str2; 6 | object ob1, ob2; 7 | function fun; 8 | 9 | if (!arg) 10 | { 11 | return notify_fail(HIY "指令格式: move_object /path/target 或者 move_object /path/ob1 to /path/ob2\n" NOR); 12 | } 13 | 14 | sscanf(arg, "%s to %s", str1, str2); 15 | 16 | if (str2) 17 | { 18 | if (!(ob1 = load_object(str1))) 19 | { 20 | return notify_fail(HIR "没有找到对象 " + str1 + "\n" NOR); 21 | } 22 | 23 | if (!(ob2 = load_object(str2))) 24 | { 25 | return notify_fail(HIR "没有找到对象 " + str2 + "\n" NOR); 26 | } 27 | msg = HIG "对象 " + str1 + " 的当前环境:" + str2 + "\n" NOR; 28 | } 29 | else 30 | { 31 | if (!(ob2 = load_object(arg))) 32 | { 33 | return notify_fail(HIR "没有找到对象 " + arg + "\n" NOR); 34 | } 35 | ob1 = me; 36 | msg = HIG "你的当前环境:" + arg + "\n" NOR; 37 | } 38 | 39 | fun = bind((: move_object :), ob1); 40 | evaluate(fun, ob2); 41 | write(msg); 42 | 43 | return 1; 44 | } 45 | -------------------------------------------------------------------------------- /cmds/efun/named_livings.c: -------------------------------------------------------------------------------- 1 | // 打印游戏所有有名字的生物 2 | int main(object me, string arg) 3 | { 4 | print_r(named_livings()); 5 | 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/efun/new.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | int id; 6 | object ob; 7 | 8 | if (!arg) 9 | { 10 | return notify_fail(HIY "指令格式: new /path/filename\n" NOR); 11 | } 12 | if (ob = new(arg)) 13 | { 14 | sscanf(file_name(ob), "%*s#%s", id); 15 | write(HIG "新对象 " + arg + " 的编号是 " + id + "\n" NOR); 16 | } 17 | else 18 | { 19 | write(HIR + arg + "载入失败!\n" NOR); 20 | } 21 | 22 | return 1; 23 | } 24 | -------------------------------------------------------------------------------- /cmds/efun/next_inventory.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | 7 | if (!arg) 8 | { 9 | cecho(next_inventory(me)); 10 | } 11 | else if (ob = load_object(arg)) 12 | { 13 | cecho(next_inventory(ob)); 14 | } 15 | else 16 | { 17 | return notify_fail(HIR "没有找到对象 " + arg + "\n" NOR); 18 | } 19 | 20 | return 1; 21 | } 22 | -------------------------------------------------------------------------------- /cmds/efun/objects.c: -------------------------------------------------------------------------------- 1 | // 打印所有载入游戏的对象 2 | int main(object me, string arg) 3 | { 4 | if (arg == "-c") 5 | print_r(objects( (:clonep:) )); 6 | else if (arg == "-o") 7 | print_r(objects( (: !clonep($1) :) )); 8 | else 9 | print_r(objects()); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/efun/query_snoop.c: -------------------------------------------------------------------------------- 1 | // query_snoop.c 2 | int main(object me, string arg) 3 | { 4 | object snooper, snoopee; 5 | 6 | if (!arg) 7 | { 8 | cecho("指令格式:query_snoop snoopee"); 9 | } 10 | else 11 | { 12 | if (!objectp(snoopee = find_player(arg))) 13 | { 14 | cecho("没有找到 " + arg + " 这个玩家,无法查看信息。"); 15 | } 16 | else if (objectp(snooper = query_snoop(snoopee))) 17 | { 18 | printf("玩家 %O 正在被玩家 %O 监听。\n", snoopee, snooper); 19 | } 20 | else 21 | { 22 | cecho("玩家 " + arg + " 没有被任何人监听。"); 23 | } 24 | } 25 | return 1; 26 | } 27 | -------------------------------------------------------------------------------- /cmds/efun/query_snooping.c: -------------------------------------------------------------------------------- 1 | // query_snooping.c 2 | int main(object me, string arg) 3 | { 4 | object snooper, snoopee; 5 | 6 | if (!arg) 7 | { 8 | cecho("指令格式:query_snooping snooper"); 9 | } 10 | else 11 | { 12 | if (!objectp(snooper = find_player(arg))) 13 | { 14 | cecho("没有找到 " + arg + " 这个玩家,无法查看信息。"); 15 | } 16 | else if (objectp(snoopee = query_snooping(snooper))) 17 | { 18 | printf("玩家 %O 正在监听玩家 %O。\n", snooper, snoopee); 19 | } 20 | else 21 | { 22 | cecho("玩家 " + arg + " 没有监听任何人。"); 23 | } 24 | } 25 | 26 | return 1; 27 | } 28 | -------------------------------------------------------------------------------- /cmds/efun/read_file.c: -------------------------------------------------------------------------------- 1 | // 查看源文件 2 | int main(object me, string arg) 3 | { 4 | if (!arg) 5 | return notify_fail("指令格式 : read_file <档案名>\n 如 : read_file /cmds/demo/2.1.1\n"); 6 | 7 | sscanf(arg, "%s.c", arg); 8 | arg = arg + ".c"; 9 | if (file_size(arg) < 0) 10 | { 11 | return notify_fail("目录下没有找到这个档案,你可以使用 get_dir 或 ls 查看列表\n"); 12 | } 13 | else 14 | { 15 | write(read_file(arg)); 16 | } 17 | 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /cmds/efun/save_object.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef __SAVE_GZ_EXTENSION__ 4 | #define __SAVE_GZ_EXTENSION__ ".o.gz" 5 | #endif 6 | #define DATA_DIR "/data/" 7 | 8 | int main(object me, string arg) 9 | { 10 | object ob; 11 | string str, file; 12 | int i; 13 | function fun; 14 | 15 | if (!arg || (sscanf(arg, "%s to %s flag %d", str, file, i) != 3)) 16 | { 17 | cecho("指令格式: save_object /path/object to save_name flag [00|01|10|11]"); 18 | } 19 | else 20 | { 21 | if (!(ob = load_object(str))) 22 | { 23 | cecho("没有找到对象 " + str); 24 | } 25 | else 26 | { 27 | file = DATA_DIR + file; 28 | fun = bind((: save_object :), ob); 29 | if (evaluate(fun, file, i)) 30 | { 31 | if (i >= 10) 32 | write(HIG "存档文件:" + file + __SAVE_GZ_EXTENSION__ + "\n" NOR); 33 | else 34 | write(HIG "存档文件:" + file + __SAVE_EXTENSION__ + "\n" NOR); 35 | } 36 | } 37 | } 38 | 39 | return 1; 40 | } 41 | -------------------------------------------------------------------------------- /cmds/efun/say.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | if (!arg) 6 | arg = "...。"; 7 | 8 | arg = HIC + arg + NOR + "\n"; 9 | 10 | write("你说到:" + arg); 11 | say(HIY + me->query("name") + "(" + geteuid(me) + ")说到:" NOR + arg); 12 | 13 | return 1; 14 | } 15 | -------------------------------------------------------------------------------- /cmds/efun/set_bit.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | string str; 4 | int i, n; 5 | 6 | if (arg && sscanf(arg, "%s %d", str, n) == 2) 7 | { 8 | arg = set_bit(str, n - 1); 9 | cecho(str); 10 | // 输出位 11 | for (i = 60; i > 0; i--) 12 | { 13 | write(test_bit(str, i - 1)); 14 | } 15 | write("\n"); 16 | cecho(arg); 17 | for (i = 60; i > 0; i--) 18 | { 19 | write(test_bit(arg, i - 1)); 20 | } 21 | write("\n"); 22 | } 23 | 24 | return 1; 25 | } 26 | -------------------------------------------------------------------------------- /cmds/efun/set_heart_beat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | string msg, str; 7 | int i; 8 | function fun; 9 | 10 | if (!arg) 11 | { 12 | return notify_fail(HIY "指令格式: set_heart_beat [/path/target] heart_beat_number\n" NOR); 13 | } 14 | sscanf(arg, "%s %d", str, i); 15 | if (i) 16 | { 17 | if (!(ob = load_object(str))) 18 | { 19 | return notify_fail(HIR "没有找到对象 " + str + "\n" NOR); 20 | } 21 | msg = HIG "对象 " + str + " 的心跳设置为 " + i + "\n" NOR; 22 | } 23 | else 24 | { 25 | ob = me; 26 | sscanf(arg, "%d", i); 27 | msg = HIG "你的心跳设置为 " + arg + "\n" NOR; 28 | } 29 | 30 | fun = bind((: set_heart_beat :), ob); 31 | evaluate(fun, i); 32 | write(msg); 33 | 34 | return 1; 35 | } 36 | -------------------------------------------------------------------------------- /cmds/efun/set_living_name.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | object ob; 6 | string msg, str1, str2; 7 | function fun; 8 | 9 | if (!arg) 10 | { 11 | return notify_fail(HIY "指令格式: set_living_name /path/target name\n" NOR); 12 | } 13 | sscanf(arg, "%s %s", str1, str2); 14 | if (str2) 15 | { 16 | if (!(ob = load_object(str1))) 17 | { 18 | return notify_fail(HIR "没有找到对象 " + str1 + "\n" NOR); 19 | } 20 | msg = HIG "对象 " + str1 + " 取名为:" + str2 + "\n" NOR; 21 | } 22 | else 23 | { 24 | ob = me; 25 | str2 = arg; 26 | msg = HIG "你的名字改为:" + arg + "\n" NOR; 27 | } 28 | 29 | fun = bind((: set_living_name :), ob); 30 | evaluate(fun, str2); 31 | write(msg); 32 | 33 | return 1; 34 | } 35 | -------------------------------------------------------------------------------- /cmds/efun/shadow.c: -------------------------------------------------------------------------------- 1 | // shadow.c 2 | int main(object me, string arg) 3 | { 4 | string str1, str2; 5 | object ob1, ob2, ob; 6 | function fun; 7 | 8 | if (!arg) 9 | { 10 | cecho("指令格式: shadow /path/target 或者 shadow /path/ob1 on /path/ob2"); 11 | } 12 | else 13 | { 14 | sscanf(arg, "%s on %s", str1, str2); 15 | 16 | if (str2) 17 | { 18 | if (!(ob1 = load_object(str1))) 19 | { 20 | cecho("没有找到对象 " + str1); 21 | } 22 | else if (ob = environment(ob1)) 23 | { 24 | cecho("对象 " + str1 + " 在环境 " + file_name(ob) + " 中"); 25 | } 26 | else if (ob = query_shadowing(ob1)) 27 | { 28 | cecho("对象 " + str1 + " 已经投影了对象 " + file_name(ob)); 29 | } 30 | else if (ob = shadow(ob1, 0)) 31 | { 32 | cecho("对象 " + str1 + " 已经被对象 " + file_name(ob) + " 投影了"); 33 | } 34 | else if (!(ob2 = load_object(str2))) 35 | { 36 | cecho("没有找到对象 " + str2); 37 | } 38 | else if (ob = query_shadowing(ob2)) 39 | { 40 | cecho("对象 " + str2 + " 已经投影了对象 " + file_name(ob)); 41 | } 42 | else 43 | { 44 | fun = bind((: shadow, ob2:), ob1); 45 | catch (evaluate(fun)); 46 | cecho("对象 " + str1 + " 投影 " + str2 + " 成功"); 47 | } 48 | } 49 | else 50 | { 51 | if (!(ob1 = load_object(arg))) 52 | { 53 | cecho("没有找到对象 " + arg); 54 | } 55 | else if (ob2 = query_shadowing(ob1)) 56 | { 57 | cecho(arg + " 投影的对象是 " + file_name(ob2)); 58 | } 59 | else if (ob2 = shadow(ob1, 0)) 60 | { 61 | cecho("对象 " + arg + " 已经被对象 " + file_name(ob2) + " 投影了"); 62 | } 63 | else 64 | { 65 | cecho(arg + " 没有投影任何对象"); 66 | } 67 | } 68 | } 69 | 70 | return 1; 71 | } 72 | -------------------------------------------------------------------------------- /cmds/efun/shout.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(object me, string arg) 4 | { 5 | if (!arg) 6 | arg = "..."; 7 | 8 | arg = HIM "【聊天】" NOR HIY + me->query("name") + "(" + geteuid(me) + "@" + MUD_NAME + "):" NOR HIC + arg + NOR "\n"; 9 | // 同步消息到QQ群 10 | if (me->query_temp("step") > 2) 11 | { 12 | "/system/daemons/qq_d"->msg(remove_ansi(arg)); 13 | } 14 | 15 | write(arg); 16 | shout(arg); 17 | 18 | return 1; 19 | } 20 | -------------------------------------------------------------------------------- /cmds/efun/shutdown.c: -------------------------------------------------------------------------------- 1 | // 关闭服务器 2 | int main(object me, string arg) 3 | { 4 | if (!wizardp(me)) 5 | { 6 | return 0; 7 | } 8 | 9 | shutdown(0); 10 | 11 | return 1; 12 | } 13 | -------------------------------------------------------------------------------- /cmds/efun/snoop.c: -------------------------------------------------------------------------------- 1 | // snoop.c 2 | int main(object me, string arg) 3 | { 4 | string arg1, arg2; 5 | object snooper, snoopee; 6 | 7 | if (!arg) 8 | { 9 | cecho("指令格式:snoop snooper [snoopee]"); 10 | } 11 | else if (sscanf(arg, "%s %s", arg1, arg2) == 2) 12 | { 13 | if (!objectp(snooper = find_player(arg1))) 14 | { 15 | cecho("没有找到 " + arg1 + " 这个玩家。"); 16 | } 17 | else if (!objectp(snoopee = find_player(arg2))) 18 | { 19 | cecho("没有找到 " + arg2 + " 这个玩家。"); 20 | } 21 | else if (snoop(snooper, snoopee)) 22 | { 23 | cecho(arg1 + " 开始窃听 " + arg2 + "。"); 24 | } 25 | else 26 | { 27 | cecho("窃听失败!"); 28 | } 29 | } 30 | else 31 | { 32 | if (!objectp(snooper = find_player(arg))) 33 | { 34 | cecho("没有找到 " + arg + " 这个玩家。"); 35 | } 36 | else if (snoop(snooper)) 37 | { 38 | cecho("已关闭 " + arg + " 的所有监听。"); 39 | } 40 | else 41 | { 42 | cecho("关闭失败!"); 43 | } 44 | } 45 | 46 | return 1; 47 | } 48 | -------------------------------------------------------------------------------- /cmds/efun/strlen.c: -------------------------------------------------------------------------------- 1 | inherit CLEAN_UP; 2 | 3 | int main(object me, string arg) 4 | { 5 | if (arg) 6 | { 7 | printf("strlen(\"%s\") = %d\n", arg, strlen(arg)); 8 | } 9 | 10 | return 1; 11 | } 12 | -------------------------------------------------------------------------------- /cmds/efun/test_bit.c: -------------------------------------------------------------------------------- 1 | int main(object me, string arg) 2 | { 3 | string str; 4 | int n; 5 | 6 | if (arg && sscanf(arg, "%s %d", str, n) == 2) 7 | { 8 | if (n < 1) 9 | { 10 | return notify_fail("最小位为 1 !\n"); 11 | } 12 | 13 | printf("字符串 %s 的第 %d 位是 %d\n", str, n, test_bit(arg, n - 1)); 14 | for (int i = 60; i > 0; i--) 15 | { 16 | write(test_bit(str, i - 1)); 17 | } 18 | write("\n"); 19 | } 20 | else 21 | { 22 | return notify_fail("格式:test_bit str n\n"); 23 | } 24 | 25 | return 1; 26 | } 27 | -------------------------------------------------------------------------------- /cmds/efun/this_player.c: -------------------------------------------------------------------------------- 1 | // this_player 2 | int main(object me, string arg) 3 | { 4 | printf("%O\n", this_player()); 5 | 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/efun/users.c: -------------------------------------------------------------------------------- 1 | // 列出游戏所有玩家对象 2 | int main(object me, string arg) 3 | { 4 | printf("%O\n", users()); 5 | 6 | return 1; 7 | } 8 | -------------------------------------------------------------------------------- /cmds/test/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !test.c 4 | !test.h 5 | -------------------------------------------------------------------------------- /cmds/test/test.c: -------------------------------------------------------------------------------- 1 | // test.c 2 | #include "test.h" 3 | 4 | int main(object me, string arg) 5 | { 6 | // 请在此实现你的代码 7 | 8 | return 1; 9 | } 10 | -------------------------------------------------------------------------------- /cmds/test/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H 2 | #define TEST_H 3 | 4 | #define SAFE(x) do { x } while (0) 5 | #define OUTPUT(x) SAFE(write(catch (error(x))); if (!this_player()) { shutdown(-1); }) 6 | #define WHERE __FILE__ + ":" + __LINE__ 7 | 8 | #include 9 | 10 | int same(mixed x, mixed y) 11 | { 12 | // Allow comparing array with buffer 13 | if (!(typeof(x) == T_ARRAY && typeof(y) == T_BUFFER || typeof(y) == T_ARRAY && typeof(x) == T_BUFFER)) 14 | if (typeof(x) != typeof(y)) 15 | return 0; 16 | switch (typeof(x)) 17 | { 18 | case T_INT: 19 | case T_STRING: 20 | case T_OBJECT: 21 | case T_FLOAT: 22 | return x == y; 23 | case T_MAPPING: 24 | if (x == y) 25 | return 1; // speed up this case 26 | if (sizeof(x) != sizeof(y)) 27 | return 0; 28 | if (!same(keys(x), keys(y))) 29 | return 0; 30 | if (!same(values(x), values(y))) 31 | return 0; 32 | return 1; 33 | case T_BUFFER: 34 | case T_ARRAY: 35 | if (x == y) 36 | return 1; // speed up this case 37 | if (sizeof(x) != sizeof(y)) 38 | return 0; 39 | for (int i = 0; i < sizeof(x); i++) 40 | { 41 | if (!same(x[i], y[i])) 42 | return 0; 43 | } 44 | return 1; 45 | case T_FUNCTION: 46 | case T_CLASS: 47 | error("Not implemented."); 48 | } 49 | } 50 | 51 | void __assert_eq(mixed expected, mixed actual, string where) 52 | { 53 | if (!same(expected, actual)) 54 | { 55 | OUTPUT(where + ", Check Failed: \n" + 56 | "Expected: \n" + sprintf("%O", expected) + "\nActual: \n" + sprintf("%O", actual) + "\n"); 57 | } 58 | } 59 | 60 | void __assert_ne(mixed expected, mixed actual, string where) 61 | { 62 | if (same(expected, actual)) 63 | { 64 | OUTPUT(where + ", Check Failed: \n" + 65 | "Expect Not: \n" + sprintf("%O", expected) + "\nActual: \n" + sprintf("%O", actual) + "\n"); 66 | } 67 | } 68 | 69 | #define ASSERT_EQ(x, y) do { __assert_eq((x), (y), WHERE); } while (0) 70 | #define ASSERT_NE(x, y) do { __assert_ne((x), (y), WHERE); } while (0) 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /config.cfg: -------------------------------------------------------------------------------- 1 | # 精简版运行时配置文件 2 | name : LPC_TEST 3 | mudlib directory : . 4 | log directory : /log 5 | include directories : /include 6 | master file : /system/kernel/master 7 | simulated efun file : /system/kernel/simul_efun 8 | global include file : 9 | debug log file : debug.log 10 | external_port_1 : telnet 4004 11 | external_port_2 : websocket 80 12 | # external_port_3 : websocket 443 13 | # external_port_3_tls : cert=cert.crt key=cert.key 14 | websocket http dir : www 15 | default fail message : 指令错误,请输入 help 查看游戏帮助。 16 | default error message : 你发现事情不大对了,但是又说不上来。 17 | # External commands(100 external cmds are supported) 18 | external_cmd_1 : /usr/bin/curl 19 | external_cmd_2 : C:\ProgramData\chocolatey\bin\curl.exe 20 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | # 如果系统未能在 log 目录下自动生成以下二个文件,请手动增加 2 | # author_stats 3 | # domain_stats 4 | * 5 | !.gitignore 6 | -------------------------------------------------------------------------------- /fix_permission.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | find . -type d -exec chmod 0755 {} + 4 | find . -type f ! -path "./fluffos/*" ! -path "./log/*" -exec chmod 0644 {} + 5 | find . -type f ! -path "./fluffos/*" ! -path "./log/*" -name "*.sh" -exec chmod 0755 {} + 6 | find . -type f ! -path "./fluffos/*" ! -path "./log/*" -name "*.py" -exec chmod 0755 {} + 7 | -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | The headers files here are shared between driver and mudlib. 2 | -------------------------------------------------------------------------------- /include/ansi.h: -------------------------------------------------------------------------------- 1 | // File : /include/ansi.h 2 | // Creator : Gothic@TMI-2 雪风@mud.ren 3 | // https://en.wikipedia.org/wiki/ANSI_escape_code 4 | // The standard set of ANSI codes for mudlib use. 5 | 6 | #ifndef ANSI_H 7 | #define ANSI_H 8 | 9 | // Control Characters 10 | #define BEEP "\07" /* Beep Sound BEL(\a) */ 11 | #define ESC "\033" /* Escape ESC(\e | \x1b) */ 12 | // Escape Sequences 13 | #define CSI ESC + "[" /* Control Sequence Introducer */ 14 | // CSI Color Sequences 15 | #define SGR(x) CSI + x + "m" /* ANSI color code (Select Graphic Rendition) */ 16 | #define FCC(x) CSI + "38;5;" + x + "m" /* Foreground 256 color code */ 17 | #define BCC(x) CSI + "48;5;" + x + "m" /* Background 256 color code */ 18 | #define RGB(r, g, b) CSI + "38;2;" + r + ";" + g + ";" + b + "m" /* Foreground 24 bit rgb color code */ 19 | #define BRGB(r, g, b) CSI + "48;2;" + r + ";" + g + ";" + b + "m" /* Background 24 bit rgb color code */ 20 | 21 | /* Foreground Colors 30 ~ 37 */ 22 | 23 | #define BLK SGR("30") /* 黑 */ 24 | #define RED SGR("31") /* 紅 */ 25 | #define GRN SGR("32") /* 綠 */ 26 | #define YEL SGR("33") /* 黃 */ 27 | #define BLU SGR("34") /* 藍 */ 28 | #define MAG SGR("35") /* 紫 */ 29 | #define CYN SGR("36") /* 青 */ 30 | #define WHT SGR("37") /* 白 */ 31 | #define FNOR SGR("39") /* 默认前景色 */ 32 | 33 | /* Hi Intensity Foreground Colors 90 ~ 97 */ 34 | 35 | #define HIK SGR("1;30") /* 灰 */ 36 | #define HIR SGR("1;31") /* 紅 */ 37 | #define HIG SGR("1;32") /* 綠 */ 38 | #define HIY SGR("1;33") /* 黃 */ 39 | #define HIB SGR("1;34") /* 藍 */ 40 | #define HIM SGR("1;35") /* 紫 */ 41 | #define HIC SGR("1;36") /* 青 */ 42 | #define HIW SGR("1;37") /* 白 */ 43 | 44 | /* Background Colors 40 ~ 47 */ 45 | 46 | #define BBLK SGR("40") /* 黑 */ 47 | #define BRED SGR("41") /* 紅 */ 48 | #define BGRN SGR("42") /* 綠 */ 49 | #define BYEL SGR("43") /* 黃 */ 50 | #define BBLU SGR("44") /* 藍 */ 51 | #define BMAG SGR("45") /* 紫 */ 52 | #define BCYN SGR("46") /* 青 */ 53 | #define BWHT SGR("47") /* 白 */ 54 | #define BNOR SGR("49") /* 默认背景色 */ 55 | 56 | /* High Intensity Background Colors 100 ~ 107 */ 57 | 58 | #define HBBLK SGR("1;40") /* 灰 */ 59 | #define HBRED SGR("1;41") /* 紅 */ 60 | #define HBGRN SGR("1;42") /* 綠 */ 61 | #define HBYEL SGR("1;43") /* 黃 */ 62 | #define HBBLU SGR("1;44") /* 藍 */ 63 | #define HBMAG SGR("1;45") /* 紫 */ 64 | #define HBCYN SGR("1;46") /* 青 */ 65 | #define HBWHT SGR("1;47") /* 白 */ 66 | 67 | // #define NOR ESC + "[m" /* Puts everything back to normal */ 68 | #define NOR SGR("0") /* 清除所有特殊属性 */ 69 | #define BOLD SGR("1") /* Turn on BOLD mode */ 70 | #define ITALIC SGR("3") /* Turn on ITALIC mode */ 71 | #define U SGR("4") /* Initialize underscore mode */ 72 | #define BLINK SGR("5") /* Initialize blink mode */ 73 | #define REV SGR("7") /* Turns reverse video mode on */ 74 | #define HIREV SGR("1;7") /* Hi intensity reverse video */ 75 | #define HIDDEN SGR("8") /* 消隐(部分客户端不支持) */ 76 | #define STRIKE SGR("9") /* Display text as strikethrough */ 77 | #define BOFF SGR("21") /* BOLD OFF */ 78 | #define IOFF SGR("23") /* ITALIC OFF */ 79 | #define UOFF SGR("24") /* UNDERLINE OFF */ 80 | #define ROFF SGR("27") /* Reverse OFF */ 81 | 82 | /* Additional ansi Esc codes added to ansi.h by Gothic april 23,1993 */ 83 | /* Note, these are Esc codes for VT100 terminals, and emmulators */ 84 | /* and they may not all work within the mud */ 85 | #define ICH(n) CSI + n + "@" /* Insert n blank characters*/ 86 | #define CUU(n) CSI + n + "A" /* (Cursor Up)光标向上移动n(默认1)格。如果光标已在屏幕边缘,则无效 */ 87 | #define CUD(n) CSI + n + "B" /* (Cursor Down)光标向下移动n(默认1)格。如果光标已在屏幕边缘,则无效 */ 88 | #define CUF(n) CSI + n + "C" /* (Cursor Forward)光标向右移动n(默认1)格。如果光标已在屏幕边缘,则无效 */ 89 | #define CUB(n) CSI + n + "D" /* (Cursor Back)光标向左移动n(默认1)格。如果光标已在屏幕边缘,则无效 */ 90 | #define CNL(n) CSI + n + "E" /* (Cursor Next Line)光标移动到下面第n(默认1)行的开头 */ 91 | #define CPL(n) CSI + n + "F" /* (Cursor Previous Line)光标移动到上面第n(默认1)行的开头 */ 92 | #define CHA(n) CSI + n + "G" /* (Cursor Horizontal Absolute)光标水平移动到第n(默认1)列 */ 93 | #define CUP(x, y) CSI + x + ";" + y + "H" /* (Cursor Position)將 cursor 移至第 x 行第 y 列 */ 94 | #define ED(n) CSI + n + "J" /* (Erase Display)0 erase from cursor to end of display, 1 erase from start of display to cursor, 2 erase display*/ 95 | #define EL(n) CSI + n + "K" /* (Erase Line)0 erase from cursor to end of line, 1 erase from start of line to cursor, 2 erase line*/ 96 | #define IL(n) CSI + n + "L" /* Insert n blank lines*/ 97 | #define DL(n) CSI + n + "M" /* Delete n lines*/ 98 | #define DCH(n) CSI + n + "P" /* Delete n characters*/ 99 | #define SPU(n) CSI + n + "S" /* Scroll whole page up by n (default 1) lines. */ 100 | #define SPD(n) CSI + n + "T" /* Scroll whole page down by n (default 1) lines. */ 101 | #define ECH(n) CSI + n + "X" /* Erase n characters*/ 102 | #define HOME CSI "H" /* Send cursor to home position */ 103 | #define CLR CSI "2J" /* Clear the screen */ 104 | #define ECL CSI "2K" /* Erase entire line. Cursor position does not change. */ 105 | #define REF CLR + HOME /* Clear screen and home cursor */ 106 | #define FREEZE(x, y) CSI + x + ";" + y + "r" /* Freeze 住從 x 到 y 這幾行作為 screen */ 107 | #define FRTOP CSI "2;25r" /* Freeze top line */ 108 | #define FRBOT CSI "1;24r" /* Freeze bottom line */ 109 | #define UNFR CSI "r" /* Unfreeze top and bottom lines */ 110 | #define SAVEC CSI "s" /* Save cursor position */ 111 | #define RESTC CSI "u" /* Restore cursor to saved position */ 112 | 113 | #define REVINDEX ESC + "M" /* Scroll screen in opposite direction */ 114 | #define BIGTOP ESC + "#3" /* Dbl height characters, top half */ 115 | #define BIGBOT ESC + "#4" /* Dbl height characters, bottem half */ 116 | #define SINGW ESC + "#5" /* Normal, single-width characters */ 117 | #define DBL ESC + "#6" /* Creates double-width characters */ 118 | #define DECALN ESC + "#8" /* DEC 屏幕校准测试 - 以E填充屏幕 */ 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /include/function.h: -------------------------------------------------------------------------------- 1 | /* codes returned by the functionp() efun */ 2 | 3 | #define FP_LOCAL 2 4 | #define FP_EFUN 3 5 | #define FP_SIMUL 4 6 | #define FP_FUNCTIONAL 5 7 | 8 | /* internal use */ 9 | #define FP_G_VAR 6 10 | #define FP_L_VAR 7 11 | #define FP_ANONYMOUS 8 12 | 13 | /* additional flags */ 14 | #define FP_MASK 0x0f 15 | #define FP_HAS_ARGUMENTS 0x10 16 | #define FP_OWNER_DESTED 0x20 17 | #define FP_NOT_BINDABLE 0x40 18 | -------------------------------------------------------------------------------- /include/globals.h: -------------------------------------------------------------------------------- 1 | /*** 2 | * @Author: 雪风@mud.ren 3 | * @Date: 2022-03-31 13:18:32 4 | * @LastEditTime: 2022-03-31 13:18:32 5 | * @LastEditors: 雪风 6 | * @Description: The global include file is included automatically 7 | * @ https://bbs.mud.ren 8 | */ 9 | 10 | #ifndef GLOBALS_H 11 | #define GLOBALS_H 12 | 13 | #ifndef __SENSIBLE_MODIFIERS__ 14 | #define nosave static 15 | #endif 16 | // 核对对象 17 | #define LOGIN_OB "/system/object/login" 18 | #define USER_OB "/system/object/user" 19 | #define VOID_OB "/system/object/void" 20 | // 守护进程(服务) 21 | #define COMBAT_D "/system/daemons/combat_d" 22 | #define MONSTER_D "/system/daemons/monster_d" 23 | #define VIRTUAL_D "/system/daemons/virtual_d" 24 | // 功能模块 25 | #define CLEAN_UP "/inherit/clean_up" 26 | #define COMBAT "/inherit/combat" 27 | #define DBASE "/inherit/dbase" 28 | #define LIVING "/inherit/living" 29 | #define OBJECT "/inherit/object" 30 | #define VERB "/inherit/verb" 31 | #define AREA "/inherit/area" 32 | #define MAZE "/inherit/maze" 33 | #define ROOM "/inherit/room" 34 | // 存档目录 35 | #define DATA_DIR "/data/" 36 | #define LOG_DIR "/log/" 37 | // 预加载列表 38 | #define PRELOAD "/system/etc/preload" 39 | // 出生地 40 | #define START_ROOM "/world/world/0,0,0" 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/localtime.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Definitions for localtime() efun 4 | */ 5 | #define LT_SEC 0 6 | #define LT_MIN 1 7 | #define LT_HOUR 2 8 | #define LT_MDAY 3 9 | #define LT_MON 4 10 | #define LT_YEAR 5 11 | #define LT_WDAY 6 12 | #define LT_YDAY 7 13 | #define LT_GMTOFF 8 14 | #define LT_ZONE 9 15 | #define LT_ISDST 10 16 | -------------------------------------------------------------------------------- /include/origin.h: -------------------------------------------------------------------------------- 1 | /* codes returned by the origin() efun */ 2 | 3 | #define ORIGIN_BACKEND "driver" /* backwards compat */ 4 | #define ORIGIN_DRIVER "driver" 5 | #define ORIGIN_LOCAL "local" 6 | #define ORIGIN_CALL_OTHER "call_other" 7 | #define ORIGIN_SIMUL_EFUN "simul" 8 | #define ORIGIN_INTERNAL "internal" 9 | #define ORIGIN_EFUN "efun" 10 | /* pseudo frames for call_other function pointers and efun pointer */ 11 | #define ORIGIN_FUNCTION_POINTER "function_pointer" 12 | /* anonymous functions */ 13 | #define ORIGIN_FUNCTIONAL "functional" 14 | -------------------------------------------------------------------------------- /include/parser_error.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSER_ERROR_H 2 | #define PARSER_ERROR_H 3 | 4 | #define ERR_IS_NOT 1 5 | #define ERR_NOT_LIVING 2 6 | #define ERR_NOT_ACCESSIBLE 3 7 | #define ERR_AMBIG 4 8 | #define ERR_ORDINAL 5 9 | #define ERR_ALLOCATED 6 10 | #define ERR_THERE_IS_NO 7 11 | #define ERR_BAD_MULTIPLE 8 12 | #define ERR_MANY_PATHS 9 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/runtime_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * runtime_config.h 3 | * 4 | * Copy this file to your mudlib include dir for use with the 5 | * get_config() efun. 6 | * 7 | * See Config.Example describing most of these settings. Some are actually 8 | * in options.h, but the mudlib doesn't have to know... 9 | * 10 | * Note for backwards compatibility: 11 | * Neither the name or the number can be changed, or reused, avoid breaking mudlib code. 12 | */ 13 | 14 | #ifndef RUNTIME_CONFIG_H 15 | #define RUNTIME_CONFIG_H 16 | 17 | #define RC_BASE_CONFIG_STR 0 18 | #define CFG_STR(x) ((x) + RC_BASE_CONFIG_STR) 19 | /* 20 | * These config settings return a string 21 | */ 22 | 23 | #define __MUD_NAME__ CFG_STR(0) 24 | #define __RC_STR_1__ CFG_STR(1) 25 | #define __MUD_LIB_DIR__ CFG_STR(2) 26 | #define __BIN_DIR__ CFG_STR(3) 27 | #define __LOG_DIR__ CFG_STR(4) 28 | #define __INCLUDE_DIRS__ CFG_STR(5) 29 | #define __RC_STR_2__ CFG_STR(6) 30 | #define __MASTER_FILE__ CFG_STR(7) 31 | #define __SIMUL_EFUN_FILE__ CFG_STR(8) 32 | #define __SWAP_FILE__ CFG_STR(9) 33 | #define __DEBUG_LOG_FILE__ CFG_STR(10) 34 | #define __DEFAULT_ERROR_MESSAGE__ CFG_STR(11) 35 | #define __DEFAULT_FAIL_MESSAGE__ CFG_STR(12) 36 | #define __GLOBAL_INCLUDE_FILE__ CFG_STR(13) 37 | #define __MUD_IP__ CFG_STR(14) 38 | #define __RC_WEBSOCKET_HTTP_DIR__ CFG_STR(15) 39 | 40 | #define RC_LAST_CONFIG_STR CFG_STR(255) 41 | /* 42 | * These config settings return an int (ie number) 43 | */ 44 | #define RC_BASE_CONFIG_INT (RC_LAST_CONFIG_STR + 1) 45 | #define CFG_INT(x) ((x) + RC_BASE_CONFIG_INT) 46 | 47 | #define __MUD_PORT__ CFG_INT(0) 48 | #define __RC_INT_1__ CFG_INT(1) 49 | #define __TIME_TO_CLEAN_UP__ CFG_INT(2) 50 | #define __TIME_TO_RESET__ CFG_INT(3) 51 | #define __TIME_TO_SWAP__ CFG_INT(4) 52 | #define __COMPILER_STACK_SIZE__ CFG_INT(5) 53 | #define __EVALUATOR_STACK_SIZE__ CFG_INT(6) 54 | #define __INHERIT_CHAIN_SIZE__ CFG_INT(7) 55 | #define __MAX_EVAL_COST__ CFG_INT(8) 56 | #define __MAX_LOCAL_VARIABLES__ CFG_INT(9) 57 | #define __MAX_CALL_DEPTH__ CFG_INT(10) 58 | #define __MAX_ARRAY_SIZE__ CFG_INT(11) 59 | #define __MAX_BUFFER_SIZE__ CFG_INT(12) 60 | #define __MAX_MAPPING_SIZE__ CFG_INT(13) 61 | #define __MAX_STRING_LENGTH__ CFG_INT(14) 62 | #define __MAX_BITFIELD_BITS__ CFG_INT(15) 63 | #define __MAX_BYTE_TRANSFER__ CFG_INT(16) 64 | #define __MAX_READ_FILE_SIZE__ CFG_INT(17) 65 | #define __RC_INT_18__ CFG_INT(18) 66 | #define __SHARED_STRING_HASH_TABLE_SIZE__ CFG_INT(19) 67 | #define __OBJECT_HASH_TABLE_SIZE__ CFG_INT(20) 68 | #define __LIVING_HASH_TABLE_SIZE__ CFG_INT(21) 69 | #define __RC_INT_22__ CFG_INT(22) 70 | #define __RC_INT_23__ CFG_INT(23) 71 | #define __RC_GAMETICK_MSEC__ CFG_INT(24) 72 | #define __RC_HEARTBEAT_INTERVAL_MSEC__ CFG_INT(25) 73 | #define __RC_SANE_EXPLODE_STRING__ CFG_INT(26) 74 | #define __RC_REVERSIBLE_EXPLODE_STRING__ CFG_INT(27) 75 | #define __RC_SANE_SORTING__ CFG_INT(28) 76 | #define __RC_WARN_TAB__ CFG_INT(29) 77 | #define __RC_WOMBLES__ CFG_INT(30) 78 | #define __RC_CALL_OTHER_TYPE_CHECK__ CFG_INT(31) 79 | #define __RC_CALL_OTHER_WARN__ CFG_INT(32) 80 | #define __RC_MUDLIB_ERROR_HANDLER__ CFG_INT(33) 81 | #define __RC_NO_RESETS__ CFG_INT(34) 82 | #define __RC_LAZY_RESETS__ CFG_INT(35) 83 | #define __RC_RANDOMIZED_RESETS__ CFG_INT(36) 84 | #define __RC_NO_ANSI__ CFG_INT(37) 85 | #define __RC_STRIP_BEFORE_PROCESS_INPUT__ CFG_INT(38) 86 | #define __RC_THIS_PLAYER_IN_CALL_OUT__ CFG_INT(39) 87 | #define __RC_TRACE__ CFG_INT(40) 88 | #define __RC_TRACE_CODE__ CFG_INT(41) 89 | #define __RC_INTERACTIVE_CATCH_TELL__ CFG_INT(42) 90 | #define __RC_RECEIVE_SNOOP__ CFG_INT(43) 91 | #define __RC_SNOOP_SHADOWED__ CFG_INT(44) 92 | #define __RC_REVERSE_DEFER__ CFG_INT(45) 93 | #define __RC_HAS_CONSOLE__ CFG_INT(46) 94 | #define __RC_NONINTERACTIVE_STDERR_WRITE__ CFG_INT(47) 95 | #define __RC_TRAP_CRASHES__ CFG_INT(48) 96 | #define __RC_OLD_TYPE_BEHAVIOR__ CFG_INT(49) 97 | #define __RC_OLD_RANGE_BEHAVIOR__ CFG_INT(50) 98 | #define __RC_WARN_OLD_RANGE_BEHAVIOR__ CFG_INT(51) 99 | #define __RC_SUPPRESS_ARGUMENT_WARNINGS__ CFG_INT(52) 100 | #define __RC_ENABLE_COMMANDS_CALL_INIT__ CFG_INT(53) 101 | #define __RC_SPRINTF_ADD_JUSTFIED_IGNORE_ANSI_COLORS__ CFG_INT(54) 102 | #define __RC_APPLY_CACHE_BITS__ CFG_INT(55) 103 | #define __RC_CALL_OUT_ZERO_NEST_LEVEL__ CFG_INT(56) 104 | #define __RC_TRACE_CONTEXT__ CFG_INT(57) 105 | #define __RC_TRACE_INSTR__ CFG_INT(58) 106 | #define __RC_ENABLE_MXP__ CFG_INT(59) 107 | #define __RC_ENABLE_GMCP__ CFG_INT(60) 108 | #define __RC_ENABLE_ZMP__ CFG_INT(61) 109 | #define __RC_ENABLE_MSSP__ CFG_INT(62) 110 | 111 | #define RC_LAST_CONFIG_INT CFG_INT(255) 112 | #endif /* RUNTIME_CONFIG_H */ 113 | -------------------------------------------------------------------------------- /include/socket_err.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socket_errors.h -- definitions for efun socket error return codes. 3 | * 5-92 : Dwayne Fontenot (Jacques@TMI) : original coding. 4 | * 10-92 : Dave Richards (Cynosure) : less original coding. 5 | */ 6 | 7 | #ifndef _SOCKET_ERRORS_H_ 8 | #define _SOCKET_ERRORS_H_ 9 | 10 | #define EESUCCESS 1 /* Call was successful */ 11 | #define EESOCKET -1 /* Problem creating socket */ 12 | #define EESETSOCKOPT -2 /* Problem with setsockopt */ 13 | #define EENONBLOCK -3 /* Problem setting non-blocking mode */ 14 | #define EENOSOCKS -4 /* UNUSED */ 15 | #define EEFDRANGE -5 /* Descriptor out of range */ 16 | #define EEBADF -6 /* Descriptor is invalid */ 17 | #define EESECURITY -7 /* Security violation attempted */ 18 | #define EEISBOUND -8 /* Socket is already bound */ 19 | #define EEADDRINUSE -9 /* Address already in use */ 20 | #define EEBIND -10 /* Problem with bind */ 21 | #define EEGETSOCKNAME -11 /* Problem with getsockname */ 22 | #define EEMODENOTSUPP -12 /* Socket mode not supported */ 23 | #define EENOADDR -13 /* Socket not bound to an address */ 24 | #define EEISCONN -14 /* Socket is already connected */ 25 | #define EELISTEN -15 /* Problem with listen */ 26 | #define EENOTLISTN -16 /* Socket not listening */ 27 | #define EEWOULDBLOCK -17 /* Operation would block */ 28 | #define EEINTR -18 /* Interrupted system call */ 29 | #define EEACCEPT -19 /* Problem with accept */ 30 | #define EEISLISTEN -20 /* Socket is listening */ 31 | #define EEBADADDR -21 /* Problem with address format */ 32 | #define EEALREADY -22 /* Operation already in progress */ 33 | #define EECONNREFUSED -23 /* Connection refused */ 34 | #define EECONNECT -24 /* Problem with connect */ 35 | #define EENOTCONN -25 /* Socket not connected */ 36 | #define EETYPENOTSUPP -26 /* Object type not supported */ 37 | #define EESENDTO -27 /* Problem with sendto */ 38 | #define EESEND -28 /* Problem with send */ 39 | #define EECALLBACK -29 /* Wait for callback */ 40 | #define EESOCKRLSD -30 /* Socket already released */ 41 | #define EESOCKNOTRLSD -31 /* Socket not released */ 42 | #define EEBADDATA -32 /* sending data with too many nested levels */ 43 | 44 | #define ERROR_STRINGS 33 /* sizeof (error_strings) */ 45 | 46 | #endif /* _SOCKET_ERRORS_H_ */ 47 | -------------------------------------------------------------------------------- /include/type.h: -------------------------------------------------------------------------------- 1 | /* /include/type.h */ 2 | 3 | #ifndef _TYPE_H 4 | #define _TYPE_H 5 | 6 | #define T_INT "int" 7 | #define T_STRING "string" 8 | #define T_ARRAY "array" 9 | #define T_OBJECT "object" 10 | #define T_MAPPING "mapping" 11 | #define T_FUNCTION "function" 12 | #define T_FLOAT "float" 13 | #define T_BUFFER "buffer" 14 | #define T_CLASS "class" 15 | 16 | #define T_INVALID "*invalid*" 17 | #define T_LVALUE "*lvalue*" 18 | #define T_LVALUE_BYTE "*lvalue_byte*" 19 | #define T_LVALUE_RANGE "*lvalue_range*" 20 | #define T_LVALUE_CODEPOINT "*lvalue_codepoint*" 21 | #define T_ERROR_HANDLER "*error_handler*" 22 | #define T_FREED "*freed*" 23 | #define T_UNKNOWN "*unknown*" 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /inherit/clean_up.c: -------------------------------------------------------------------------------- 1 | // clean_up.c 2 | #define NEVER_AGAIN 0 3 | #define AGAIN 1 4 | 5 | int clean_up(int inherited) 6 | { 7 | object *inv; 8 | 9 | // 在线游戏玩家不清除 10 | if (interactive(this_object())) 11 | return AGAIN; 12 | // 在环境中的对象不主动清除(通过清除环境来清理) 13 | if (environment()) 14 | return AGAIN; 15 | // 如果环境中有玩家则不清除环境 16 | inv = all_inventory(); 17 | for (int i = sizeof(inv) - 1; i >= 0; i--) 18 | if (interactive(inv[i])) 19 | return AGAIN; 20 | 21 | destruct(this_object()); 22 | return NEVER_AGAIN; 23 | } 24 | -------------------------------------------------------------------------------- /inherit/combat.c: -------------------------------------------------------------------------------- 1 | // 战斗模块F_COMBAT 2 | 3 | int can_fight() { return 1; } 4 | 5 | // 敌人列表 6 | nosave object *enemies = ({}); 7 | // 获取敌人列表 8 | object *query_enemy() { return enemies; } 9 | 10 | // 判断是否在战斗中或在和指定对象战斗 11 | varargs int is_fighting(object ob) 12 | { 13 | if (!ob) 14 | return sizeof(enemies) > 0; 15 | 16 | return member_array(ob, enemies) != -1; 17 | } 18 | 19 | // 和指定对象开始战斗 20 | void fight(object ob) 21 | { 22 | if (member_array(ob, enemies) == -1) 23 | { 24 | enemies += ({ob}); 25 | } 26 | } 27 | 28 | // 清理无效敌人 29 | void clean_up_enemy() 30 | { 31 | int i; 32 | if (i = sizeof(enemies)) 33 | { 34 | while (i--) 35 | { 36 | if (!objectp(enemies[i]) || (environment(enemies[i]) != environment())) 37 | { 38 | enemies[i] = 0; 39 | } 40 | } 41 | enemies -= ({0}); 42 | } 43 | } 44 | 45 | // 移除指定敌人 46 | int remove_enemy(object ob) 47 | { 48 | enemies -= ({ob}); 49 | return 1; 50 | } 51 | 52 | // 清除所有敌人 53 | void remove_all_enemy() 54 | { 55 | enemies = ({}); 56 | } 57 | 58 | // 开始攻击随机敌人 59 | void attack() 60 | { 61 | object me = this_object(), opponent; 62 | 63 | clean_up_enemy(); 64 | if (sizeof(enemies) && objectp(opponent = element_of(enemies))) 65 | { 66 | COMBAT_D->fight(me, opponent); 67 | } 68 | } 69 | 70 | // 死亡处理 71 | void die() 72 | { 73 | object me = this_object(); 74 | remove_all_enemy(); 75 | msg("danger", "$ME死亡了。", me); 76 | if (userp(me)) 77 | { 78 | me->move(START_ROOM); 79 | me->set("hp", me->query("max_hp")); 80 | } 81 | else 82 | { 83 | // todo 战斗奖励 84 | destruct(me); 85 | } 86 | } 87 | 88 | void heart_beat() 89 | { 90 | object me = this_object(); 91 | // 死亡相关控制 92 | if (me->query("hp") < 0) 93 | { 94 | die(); 95 | } 96 | // 行动相关控制 97 | if (is_fighting()) 98 | { 99 | // 怪物HP少于1/3时有1/3机率变身暗天使 100 | if (!userp(me) && !shadow(me, 0) && !query_shadowing(me) && me->query("hp") < me->query("hp") / 3 && !random(3)) 101 | { 102 | object ob = new ("/world/world/npc/mob", 8); 103 | msg("danger", me->query("name") + "变身为" + ob->query("name") + "。", me); 104 | ob->shadowto(me); 105 | } 106 | else 107 | { 108 | // 战斗吧,皮卡丘 109 | attack(); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /inherit/dbase.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright: 2019, Mud.Ren 3 | File name: dbase.c 4 | Description: 数据存取接口 5 | Author: xuefeng 6 | Version: v1.0 7 | Date: 2019-09-15 8 | *****************************************************************************/ 9 | mapping dbase; 10 | nosave mapping tmp_dbase; 11 | 12 | // void create(){} 13 | 14 | mixed _set(mapping map, string *parts, mixed value) 15 | { 16 | if (sizeof(parts) == 1) 17 | return map[parts[0]] = value; 18 | 19 | if (!map[parts[0]] || !mapp(map[parts[0]])) 20 | map[parts[0]] = ([parts[1]:0]); 21 | 22 | return _set(map[parts[0]], parts[1..sizeof(parts)-1], value); 23 | } 24 | 25 | mixed _query(mapping map, string *parts) 26 | { 27 | mixed value; 28 | int i, s; 29 | 30 | value = map; 31 | s = sizeof(parts); 32 | for (i = 0; i < s; i++) 33 | { 34 | if (undefinedp(value = value[parts[i]])) 35 | break; 36 | if (!mapp(value)) 37 | break; 38 | } 39 | return value; 40 | } 41 | 42 | int _delete(mapping map, string *parts) 43 | { 44 | if (sizeof(parts) == 1) 45 | { 46 | map_delete(map, parts[0]); 47 | return 1; 48 | } 49 | if (!map[parts[0]] || !mapp(map[parts[0]])) 50 | return 0; 51 | return _delete(map[parts[0]], parts[1..sizeof(parts)-1]); 52 | } 53 | 54 | mixed set(string prop, mixed data) 55 | { 56 | if (!mapp(dbase)) 57 | dbase = ([]); 58 | 59 | if (strsrch(prop, '/') != -1) 60 | return _set(dbase, explode(prop, "/"), data); 61 | 62 | return dbase[prop] = data; 63 | } 64 | 65 | varargs mixed query(string prop, int raw) 66 | { 67 | mixed data; 68 | 69 | if (!mapp(dbase)) 70 | return 0; 71 | 72 | if (undefinedp(dbase[prop]) && (strsrch(prop, '/') != -1)) 73 | data = _query(dbase, explode(prop, "/")); 74 | else 75 | data = dbase[prop]; 76 | 77 | if (raw) 78 | return data; 79 | 80 | return evaluate(data, this_object()); 81 | } 82 | 83 | int delete(string prop) 84 | { 85 | if (!mapp(dbase)) 86 | return 0; 87 | 88 | if (strsrch(prop, '/') != -1) 89 | return _delete(dbase, explode(prop, "/")); 90 | else 91 | { 92 | map_delete(dbase, prop); 93 | return 1; 94 | } 95 | } 96 | 97 | mixed add(string prop, mixed data) 98 | { 99 | mixed old; 100 | 101 | if (!mapp(dbase) || !(old = query(prop, 1))) 102 | return set(prop, data); 103 | 104 | if (functionp(old)) 105 | error("dbase: add() - called on a function type property.\n"); 106 | 107 | return set(prop, old + data); 108 | } 109 | 110 | mapping query_entire_dbase() 111 | { 112 | return dbase; 113 | } 114 | 115 | void set_dbase(mapping data) 116 | { 117 | if (!mapp(data)) 118 | return; 119 | 120 | dbase = data; 121 | } 122 | 123 | mixed set_temp(string prop, mixed data) 124 | { 125 | if (!mapp(tmp_dbase)) 126 | tmp_dbase = ([]); 127 | 128 | if (strsrch(prop, '/') != -1) 129 | return _set(tmp_dbase, explode(prop, "/"), data); 130 | 131 | return tmp_dbase[prop] = data; 132 | } 133 | 134 | varargs mixed query_temp(string prop, int raw) 135 | { 136 | mixed data; 137 | 138 | if (!mapp(tmp_dbase)) 139 | return 0; 140 | 141 | if (strsrch(prop, '/') != -1) 142 | data = _query(tmp_dbase, explode(prop, "/")); 143 | else 144 | data = tmp_dbase[prop]; 145 | 146 | if (functionp(data) && !raw) 147 | return (*data)(this_object()); 148 | else 149 | return data; 150 | } 151 | 152 | int delete_temp(string prop) 153 | { 154 | if (!mapp(tmp_dbase)) 155 | return 0; 156 | 157 | if (strsrch(prop, '/') != -1) 158 | return _delete(tmp_dbase, explode(prop, "/")); 159 | else 160 | { 161 | map_delete(tmp_dbase, prop); 162 | return 1; 163 | } 164 | } 165 | 166 | mixed add_temp(string prop, mixed data) 167 | { 168 | mixed old; 169 | 170 | if (!mapp(tmp_dbase) || !(old = query_temp(prop, 1))) 171 | return set_temp(prop, data); 172 | 173 | if (functionp(old)) 174 | error("dbase: add_temp() - called on a function type property.\n"); 175 | 176 | return set_temp(prop, old + data); 177 | } 178 | 179 | mapping query_entire_temp_dbase() 180 | { 181 | return tmp_dbase; 182 | } 183 | 184 | void set_temp_dbase(mapping data) 185 | { 186 | if (!mapp(data)) 187 | return; 188 | 189 | tmp_dbase = data; 190 | } 191 | -------------------------------------------------------------------------------- /inherit/living.c: -------------------------------------------------------------------------------- 1 | // 生物对象公共方法 2 | inherit OBJECT; 3 | inherit VERB; 4 | 5 | #define CMD_PATH "/cmds/cmd/" 6 | #define DEMO_PATH "/cmds/demo/" 7 | #define EFUN_PATH "/cmds/efun/" 8 | #define TEST_PATH "/cmds/test/" 9 | 10 | int is_living() { return 1; } 11 | 12 | void set_living(string id) 13 | { 14 | enable_commands(); 15 | if (id) 16 | { 17 | set_living_name(id); 18 | seteuid(id); 19 | } 20 | add_action("command_hook", "", 1); 21 | } 22 | 23 | // NPC消息界面 catch_tell() 24 | // void catch_tell(string msg) 25 | // { 26 | // debug_message(this_object() + msg); 27 | // } 28 | 29 | // 生物执行指令接口 30 | int command(string cmd) 31 | { 32 | return efun::command(cmd); 33 | } 34 | 35 | nomask int command_hook(string arg) 36 | { 37 | string verb, cmd, test, efun_cmd, demo; 38 | object me, cmd_ob; 39 | 40 | verb = query_verb(); 41 | cmd = CMD_PATH + verb; 42 | test = TEST_PATH + verb; 43 | efun_cmd = EFUN_PATH + verb; 44 | demo = DEMO_PATH + verb; 45 | me = this_object(); 46 | 47 | if ((verb = trim(verb)) == "") 48 | return 0; 49 | 50 | if (!arg && (objectp(environment()) && environment()->query("exits/" + verb))) 51 | { 52 | me->command("go " + verb); 53 | } 54 | else if (cmd_ob = load_object(cmd) || cmd_ob = load_object(test) || cmd_ob = load_object(efun_cmd) || cmd_ob = load_object(demo)) 55 | { 56 | return (int)cmd_ob->main(me, arg); 57 | } 58 | else 59 | { 60 | mixed err = parse_sentence(arg ? verb + " " + arg : verb, 0); 61 | if (intp(err)) 62 | { 63 | switch (err) 64 | { 65 | case 1: // verb 匹配成功 66 | return 1; 67 | default: 68 | return 0; 69 | } 70 | } 71 | return notify_fail(err); 72 | } 73 | 74 | return 1; 75 | } 76 | -------------------------------------------------------------------------------- /inherit/object.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 雪风@mud.ren 3 | * @Date: 2022-04-01 10:51:31 4 | * @LastEditTime: 2022-04-03 19:16:02 5 | * @LastEditors: 雪风 6 | * @Description: 游戏实体对象(不包括环境)公共方法 7 | * https://bbs.mud.ren 8 | */ 9 | 10 | inherit DBASE; 11 | 12 | // present() 调用 - 通过 id 查找对象 13 | int id(string id) 14 | { 15 | return (geteuid() == id) || (geteuid()[0..0] == id); 16 | } 17 | 18 | // parser 调用,根据字符串查询对象 19 | string *parse_command_id_list() 20 | { 21 | return ({geteuid(), geteuid()[0..0]}); 22 | } 23 | 24 | // 方便移动对象到指定环境 25 | int move(mixed dest) 26 | { 27 | object me = this_object(); 28 | object env = environment(me); 29 | 30 | // 如果由area移出, 在這做move_out動作 31 | if (env && env->is_area()) 32 | { 33 | mapping info; 34 | info = me->query("area_info"); 35 | env->move_out(info["x_axis_old"], info["y_axis_old"], me); 36 | } 37 | 38 | move_object(dest); 39 | 40 | // 如果移入的不是區域或虚空,則刪除area_info 41 | if (me->query("area_info") && !dest->is_area() && !dest->query("void")) 42 | { 43 | me->delete("area_info"); 44 | } 45 | // 对没有用area_move到area的移动到随机坐标 46 | if (dest->is_area() && !me->query("area_info")) 47 | { 48 | // debug_message(sprintf("[!]%O -> %O", me, dest)); 49 | me->set("area_info/x_axis", random(dest->query("x_axis_size"))); 50 | me->set("area_info/y_axis", random(dest->query("y_axis_size"))); 51 | } 52 | 53 | if (interactive(me)) 54 | { 55 | command("look"); 56 | } 57 | 58 | return 1; 59 | } 60 | 61 | void move_or_destruct(object dest) 62 | { 63 | if (dest) 64 | { 65 | move(dest); 66 | } 67 | else 68 | { 69 | cecho("突然一阵时空扭曲,你被传送到虚空。"); 70 | move(VOID_OB); 71 | } 72 | } 73 | 74 | // 对象简称 75 | string short() 76 | { 77 | return sprintf("%s(%s)", query("name")||"???", geteuid()); 78 | } 79 | 80 | // 对象描述 81 | string long() 82 | { 83 | return query("long") || short(); 84 | } 85 | -------------------------------------------------------------------------------- /inherit/room.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 雪风@mud.ren 3 | * @Date: 2022-03-31 15:20:12 4 | * @LastEditTime: 2022-03-31 15:20:12 5 | * @LastEditors: 雪风 6 | * @Description: 通用游戏环境设置接口,通过reset()自动加载物品对象到房间 7 | * https://bbs.mud.ren 8 | */ 9 | inherit CLEAN_UP; 10 | inherit DBASE; 11 | 12 | // void create(){} 13 | 14 | object make_inventory(string file) 15 | { 16 | object ob; 17 | 18 | if(!objectp(ob = new(file))) 19 | return 0; 20 | ob->move(this_object()); 21 | return ob; 22 | } 23 | 24 | // driver自动定期呼叫此apply 25 | void reset() 26 | { 27 | /** 28 | * ob_list:需要加载的对象map列表 29 | * ob:加载后的对象map列表 30 | */ 31 | mapping ob_list, ob; 32 | string file; 33 | int amount; 34 | 35 | if (!mapp(ob_list = query("objects"))) 36 | return; 37 | 38 | if (!mapp(ob = query_temp("objects"))) 39 | ob = ([]); 40 | 41 | foreach(file, amount in ob_list) 42 | { 43 | if (amount == 1) 44 | { 45 | if(!objectp(ob[file])) 46 | ob[file] = make_inventory(file); 47 | } 48 | else 49 | { 50 | if (!arrayp(ob[file]) || (sizeof(ob[file]) != amount)) 51 | ob[file] = allocate(amount); 52 | for(int i = 0; i < amount; i++) 53 | { 54 | if(!objectp(ob[file][i])) 55 | ob[file][i] = make_inventory(file); 56 | } 57 | } 58 | } 59 | // 缓存对象列表 60 | set_temp("objects", ob); 61 | } 62 | 63 | void setup() 64 | { 65 | reset(); 66 | } 67 | 68 | // 移除一个出口 69 | void removeExit(string dir) 70 | { 71 | mapping exits = query("exits"); 72 | if (mapp(exits) && exits[dir]) 73 | map_delete(exits, dir); 74 | } 75 | 76 | // 移除随机出口 77 | void removeRandomExit() 78 | { 79 | mapping exits = query("exits"); 80 | if (mapp(exits) && sizeof(exits) > 1) 81 | { 82 | removeExit(element_of(keys(exits))); 83 | } 84 | } 85 | 86 | // 增加一个出口 87 | void addExit(string dir, string dest) 88 | { 89 | mapping exits = query("exits"); 90 | if (!mapp(exits)) 91 | exits = ([]); 92 | if (!exits[dir]) 93 | exits[dir] = dest; 94 | } 95 | -------------------------------------------------------------------------------- /inherit/user1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 雪风@mud.ren 3 | * @Date: 2022-03-31 15:04:35 4 | * @LastEditTime: 2022-05-11 15:13:34 5 | * @LastEditors: 雪风 6 | * @Description: 自定义 user 对象 7 | * https://bbs.mud.ren 8 | */ 9 | #include 10 | inherit LIVING; 11 | 12 | varargs void create(string arg) 13 | { 14 | if (clonep()) 15 | { 16 | string *name1 = ({"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨"}); 17 | string *name2 = ({"春", "夏", "秋", "冬", "风", "花", "雪", "月", "天", "地", "玄", "黄", "宇", "宙", "洪", "荒"}); 18 | 19 | ::create(); 20 | set_living(arg); 21 | set("gender", random(2) ? "男" : "女"); 22 | set("name", element_of(name1) + element_of(name2)); 23 | move_object(START_ROOM); 24 | } 25 | else 26 | { 27 | // 自动加载VERB指令 28 | map(get_dir("/verbs/*.c"), function(string file) { 29 | return "/verbs/" + file; 30 | })->load(); 31 | } 32 | } 33 | 34 | void net_dead() 35 | { 36 | say(HIR "玩家(" + geteuid() + ")离开了游戏。\n" NOR); 37 | destruct(); 38 | } 39 | -------------------------------------------------------------------------------- /inherit/user2.c: -------------------------------------------------------------------------------- 1 | inherit __DIR__ "user1"; 2 | 3 | // apply函数:如果用户对象中有process_input(),驱动会将玩家所有输入传入这里 4 | // 如果 process_input() 方法返回字符串,此字符串会取代玩家的输入;如果返回 0 则保持玩家输入的内容不变;如果返回 1 则完全过滤掉此输入内容,不再做任何处理。 5 | mixed process_input(string verb) 6 | { 7 | string *word = explode(verb, " "); 8 | mapping alias = ([ 9 | "s":"go south", 10 | "n":"go north", 11 | "w":"go west", 12 | "e":"go east", 13 | "sd":"go southdown", 14 | "nd":"go northdown", 15 | "wd":"go westdown", 16 | "ed":"go eastdown", 17 | "su":"go southup", 18 | "nu":"go northup", 19 | "wu":"go westup", 20 | "eu":"go eastup", 21 | "sw":"go southwest", 22 | "se":"go southeast", 23 | "nw":"go northwest", 24 | "ne":"go northeast", 25 | "d":"go down", 26 | "u":"go up", 27 | "chat":"shout", 28 | "who":"users", 29 | "i":"all_inventory", 30 | "ls":"get_dir", 31 | "sa":"area_set", 32 | ]); 33 | 34 | // verb = lower_case(verb); 35 | 36 | switch (verb[0]) 37 | { 38 | case '.': 39 | return "say " + verb[1..]; 40 | } 41 | 42 | if (sizeof(word) && !undefinedp(alias[word[0]])) 43 | { 44 | word[0] = alias[word[0]]; 45 | return implode(word, " "); 46 | } 47 | 48 | return verb; 49 | } 50 | -------------------------------------------------------------------------------- /inherit/user3.c: -------------------------------------------------------------------------------- 1 | // user3.c 2 | #include 3 | inherit __DIR__ "user2"; 4 | 5 | void receive_message(string type, string message) 6 | { 7 | // 可以在此判断是否显示消息等 8 | switch (type) 9 | { 10 | case "emote": 11 | receive(HIM + message + "\n" NOR); 12 | break; 13 | case "success": 14 | receive(HIG + message + "\n" NOR); 15 | break; 16 | case "danger": 17 | receive(HIR + message + "\n" NOR); 18 | break; 19 | case "warning": 20 | receive(HIY + message + "\n" NOR); 21 | break; 22 | case "info": 23 | receive(HIC + message + "\n" NOR); 24 | break; 25 | case "MAP": 26 | receive(message); 27 | break; 28 | default: 29 | receive(HIW + message + "\n" NOR); 30 | } 31 | } 32 | 33 | void receive_snoop(string message) 34 | { 35 | receive(HBBLU + message + NOR); 36 | } 37 | -------------------------------------------------------------------------------- /inherit/user4.c: -------------------------------------------------------------------------------- 1 | // user4.c 2 | #include 3 | 4 | inherit __DIR__ "user3"; 5 | inherit __DIR__ "combat"; // 战斗模块 6 | 7 | varargs void create(string arg) 8 | { 9 | ::create(arg); 10 | if (clonep()) 11 | { 12 | int lv = random(100) + 1; 13 | set("lv", lv); 14 | set("max_hp", 10 * lv + random(10)); 15 | set("hp", query("max_hp")); 16 | set("str", 4 * lv + random(10)); 17 | set("def", 3 * lv + random(10)); 18 | set("agi", 2 * lv + random(10)); 19 | 20 | set_heart_beat(1); 21 | } 22 | } 23 | 24 | void write_prompt() 25 | { 26 | write(sprintf("[%s|%s]", GRN + query("hp") + NOR, HIG + query("max_hp") + NOR)); 27 | } 28 | -------------------------------------------------------------------------------- /inherit/user5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 雪风@mud.ren 3 | * @Date: 2021-09-05 12:15:32 4 | * @LastEditTime: 2022-03-31 14:23:41 5 | * @LastEditors: 雪风 6 | * @Description: 玩家存档与读档接口 7 | * https://bbs.mud.ren 8 | */ 9 | inherit __DIR__ "user4"; 10 | 11 | // void create(){} 12 | 13 | // 指定存档位置 14 | varargs string query_save_file(string data) 15 | { 16 | return "/data/" + (data || geteuid(this_object())); 17 | } 18 | 19 | varargs int save(string data) 20 | { 21 | string file; 22 | 23 | if (stringp(file = this_object()->query_save_file(data))) 24 | return save_object(file); 25 | 26 | return 0; 27 | } 28 | 29 | varargs int load(string data) 30 | { 31 | string file; 32 | 33 | if (stringp(file = this_object()->query_save_file(data))) 34 | return restore_object(file); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /inherit/user6.c: -------------------------------------------------------------------------------- 1 | inherit __DIR__ "user5"; 2 | 3 | // 客户端窗口大小 4 | void window_size(int width, int height) 5 | { 6 | string msg = sprintf("TELNET NAWS: %dx%d\n", width, height); 7 | receive(msg); 8 | } 9 | 10 | // receive_environ 11 | void receive_environ(string var, string value) 12 | { 13 | string msg = sprintf("TELNET ENV received: %s=%s\n", var, value); 14 | receive(msg); 15 | } 16 | 17 | void mxp_enable() 18 | { 19 | receive("\n"); 20 | } 21 | 22 | void gmcp_enable() 23 | { 24 | receive("\n"); 25 | } 26 | 27 | void gmcp(string req) 28 | { 29 | receive("\n"); 30 | receive(req); 31 | receive("\n\n"); 32 | } 33 | 34 | void mxp_tag(string command) 35 | { 36 | receive("\n"); 37 | } 38 | 39 | void act_mxp() 40 | { 41 | #if efun_defined(act_mxp) 42 | efun::act_mxp(); 43 | #endif 44 | } 45 | 46 | // 发送gmcp数据到客户端 47 | void send_gmcp(string req) 48 | { 49 | #if efun_defined(send_gmcp) 50 | efun::send_gmcp(req); 51 | #else 52 | receive("当前驱动不支持efun send_gmcp\n"); 53 | #endif 54 | } 55 | 56 | void msp_enable() 57 | { 58 | receive("\n"); 59 | } 60 | 61 | // 发送msp数据到客户端 62 | void msp_oob(string req) 63 | { 64 | #if efun_defined(telnet_msp_oob) 65 | efun::telnet_msp_oob(req); 66 | #else 67 | receive("当前驱动不支持efun telnet_msp_oob\n"); 68 | #endif 69 | } 70 | -------------------------------------------------------------------------------- /inherit/verb.c: -------------------------------------------------------------------------------- 1 | // Parser 指令公共方法 2 | private nosave string Verb, ErrorMessage; 3 | private nosave string *Synonyms, *Rules; 4 | 5 | protected void create() 6 | { 7 | parse_init(); 8 | Verb = 0; 9 | ErrorMessage = 0; 10 | Rules = ({}); 11 | Synonyms = ({}); 12 | } 13 | 14 | protected string setErrorMessage(string str) { return (ErrorMessage = str); } 15 | 16 | string getErrorMessage() { return ErrorMessage; } 17 | 18 | varargs protected string *setRules(mixed *args...) 19 | { 20 | if (sizeof(Rules)) 21 | error("Cannot reset rules list."); 22 | foreach (mixed arg in args) 23 | { 24 | if (stringp(arg)) 25 | Rules += ({arg}); 26 | else 27 | Rules += arg; 28 | } 29 | if (Verb) 30 | { 31 | foreach (string rule in Rules) 32 | parse_add_rule(Verb, rule); 33 | if (sizeof(Synonyms)) 34 | foreach (string cmd in Synonyms) 35 | parse_add_synonym(cmd, Verb); 36 | } 37 | return Rules; 38 | } 39 | 40 | string *getRules() { return copy(Rules); } 41 | 42 | varargs protected string *setSynonyms(mixed *args...) 43 | { 44 | if (sizeof(Synonyms)) 45 | error("Cannot reset synonym list.\n"); 46 | foreach (mixed arg in args) 47 | { 48 | if (stringp(arg)) 49 | Synonyms += ({arg}); 50 | else 51 | Synonyms += arg; 52 | } 53 | if (Verb && sizeof(Rules)) 54 | foreach (string cmd in Synonyms) 55 | parse_add_synonym(cmd, Verb); 56 | return Synonyms; 57 | } 58 | 59 | string *getSynonyms() { return copy(Synonyms); } 60 | 61 | protected string setVerb(string str) 62 | { 63 | if (!stringp(str)) 64 | error("Bad argument 1 to setVerb().\n"); 65 | Verb = str; 66 | if (sizeof(Rules)) 67 | foreach (string rule in Rules) 68 | parse_add_rule(Verb, rule); 69 | if (sizeof(Synonyms)) 70 | foreach (string cmd in Synonyms) 71 | parse_add_synonym(cmd, Verb); 72 | return Verb; 73 | } 74 | 75 | string getVerb() { return Verb; } 76 | 77 | string *getVerbs() { return ({Verb}); } 78 | -------------------------------------------------------------------------------- /log/.gitignore: -------------------------------------------------------------------------------- 1 | # 如果系统未能在 log 目录下自动生成以下二个文件,请手动增加 2 | # author_stats 3 | # domain_stats 4 | * 5 | !.gitignore 6 | -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | if not exist "driver.exe" ( 3 | echo driver.exe not found, please compile with build_msys2.sh... 4 | pause 5 | ) else ( 6 | start /B "" "driver.exe" "config.cfg" 7 | color 02 8 | ) 9 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 判断 driver 文件是否存在 4 | if [ -f "fluffos/build/bin/driver" ]; then 5 | # 如果 driver 文件存在,则运行 ./fluffos/build/bin/driver config.cfg 6 | cd $(dirname "$0") 7 | ./fluffos/build/bin/driver config.ini 8 | else 9 | # 如果 driver 文件不存在,则提示请先运行 build.sh 编译 driver 10 | echo "Please run build.sh first to compile the driver." 11 | fi 12 | -------------------------------------------------------------------------------- /system/daemons/combat_d.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 战斗伤害类型 4 | #define TYPE_N 0 // 普通攻击 5 | #define TYPE_C 1 // 会心一击 6 | 7 | // 攻击信息 8 | nosave string *attack_msg = ({ 9 | "$ME无视$YOU的行动,全力发起攻击。", 10 | "$ME盯著$YOU的一举一动,乘$YOU没有防备突然出招。", 11 | "$ME慢慢地移动著脚步,然后快速攻击。", 12 | }); 13 | // 防御攻击信息 14 | nosave string *guard_msg = ({ 15 | "但是$ME的攻击被$YOU格挡了。", 16 | "但是$YOU已有准备,不慌不忙的格挡住$ME的攻击。", 17 | }); 18 | // 躲避攻击信息 19 | nosave string *dodge_msg = ({ 20 | "但是$ME的攻击被$YOU机灵地躲开了。", 21 | "但是$YOU左避右闪,躲过了$ME的攻击。", 22 | "但是$YOU已有准备,不慌不忙的躲开了$ME的攻击。", 23 | }); 24 | // 伤害信息 25 | string damage_msg(int damage, int type) 26 | { 27 | if (damage == 0) 28 | { 29 | switch (random(3)) 30 | { 31 | case 1: 32 | return element_of(guard_msg); 33 | case 2: 34 | return element_of(dodge_msg); 35 | default: 36 | return "但是$ME的攻击对$YOU没有造成任何伤害。"; 37 | } 38 | } 39 | 40 | switch (type) 41 | { 42 | case TYPE_C: 43 | return YEL "$ME发动会心一击,对$YOU造成了 " + damage + " 点爆击伤害。"; 44 | default: 45 | return "$ME对$YOU造成了 " + damage + " 点伤害。"; 46 | } 47 | } 48 | 49 | void create() 50 | { 51 | } 52 | 53 | // 攻击处理 54 | void do_attack(object me, object victim) 55 | { 56 | /** 57 | * 物理伤害计算方法 58 | * [伤害计算值]=(攻击力/2-防御力/4)+1 59 | * [伤害波动]=[伤害计算值]/16+1 60 | * [实际伤害值]=[伤害计算值]±[伤害波动] 61 | */ 62 | int attack, damage, defense, random, attack_type = TYPE_N; 63 | 64 | attack = me->query("str"); 65 | defense = me->query("def"); 66 | damage = attack / 2 - defense / 4 + 1; 67 | 68 | /** 69 | * 会心伤害(暴击)无视防御 70 | * [会心伤害基础值]=攻击力 71 | */ 72 | if (random(100) < random(me->query("agi"))) 73 | { 74 | damage = attack; 75 | attack_type = TYPE_C; 76 | } 77 | // 伤害波动 78 | random = damage / 16 + 1; 79 | if (random(2)) 80 | { 81 | damage += random; 82 | } 83 | else 84 | { 85 | damage -= random; 86 | } 87 | 88 | if (damage < 0) 89 | { 90 | damage = random(3); 91 | } 92 | 93 | victim->set("hp", victim->query("hp") - damage); 94 | msg("success", damage_msg(damage, attack_type), me, victim); 95 | } 96 | 97 | // 战斗回合处理 98 | void fight(object me, object victim) 99 | { 100 | // 避免隔空战斗 101 | if (environment(me) != environment(victim)) 102 | { 103 | return; 104 | } 105 | 106 | if (!victim->is_fighting(me)) 107 | { 108 | victim->fight(me); 109 | } 110 | 111 | msg("info", element_of(attack_msg), me, victim); 112 | do_attack(me, victim); 113 | } 114 | -------------------------------------------------------------------------------- /system/daemons/monster_d.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright: 2021, Mud.Ren 3 | File name: monster_d.c 4 | Description: 游戏怪物守护进程 5 | Author: xuefeng@mud.ren 6 | Version: v1.0 7 | *****************************************************************************/ 8 | /* 9 | * ID, Name, HP, 攻, 防, 速, EXP, Gold 10 | */ 11 | nosave mixed mob_info = ({ 12 | ({"mob", "小恶魔", 7, 6, 5, 4, 2, 1}), 13 | ({"mob1", "迷雾树人", 14, 12, 10, 8, 4, 2}), 14 | ({"mob2", "人脸玫瑰", 21, 18, 15, 12, 6, 3}), 15 | ({"mob3", "千面狩猎者", 28, 24, 20, 16, 8, 4}), 16 | ({"mob4", "六翼石像鬼", 35, 30, 25, 20, 10, 5}), 17 | ({"mob5", "诡术邪怪", 42, 36, 30, 24, 12, 6}), 18 | ({"mob6", "灵界掠夺者", 49, 42, 35, 28, 14, 7}), 19 | ({"mob7", "梦境捕手", 70, 60, 50, 40, 20, 10}), 20 | ({"mob8", "暗天使", 100, 90, 70, 50, 30, 15}), 21 | ({"mob9", "暗天使恶灵", 150, 130, 120, 100, 50, 20}), 22 | }); 23 | 24 | // 超出范围则随机返回 25 | int limit(int index) 26 | { 27 | if (index < 1 || index >= sizeof(mob_info)) 28 | index = 1 + random(sizeof(mob_info) - 1); 29 | return index; 30 | } 31 | 32 | mixed info(int index) 33 | { 34 | index = limit(index); 35 | return mob_info[index]; 36 | } 37 | -------------------------------------------------------------------------------- /system/daemons/qq_d.c: -------------------------------------------------------------------------------- 1 | /** QQ_D QQ群消息转发机器人 2 | * 3 | * 机器人服务端使用mirai开源框架,需要自己配置QQ API服务器 4 | * 服务器配置文档:https://github.com/project-mirai/mirai-api-http 5 | * 6 | */ 7 | #include 8 | 9 | #define STREAM 1 10 | #define EESUCCESS 1 11 | // QQ消息API服务器配置 12 | nosave string host = "mud.ren"; 13 | nosave string addr = "118.190.104.241 8006"; 14 | nosave string mirai_verifyKey = "QQ7300637-6427"; 15 | nosave string mirai_qq = "21791131"; 16 | // 游戏消息转发到指定的QQ群 17 | nosave string group = "285533476"; 18 | nosave mapping status = ([]); 19 | nosave string session; 20 | 21 | private void bind(); 22 | private void websocket(); 23 | 24 | private void http(int fd) 25 | { 26 | socket_write(fd, status[fd]["http"]); 27 | } 28 | 29 | private void receive_verify(int fd, mixed result) 30 | { 31 | int n = strsrch(result, "{"); 32 | // debug_message(result); 33 | if (n > 0) 34 | { 35 | mixed json; 36 | json = json_decode(trim(result[n..])); 37 | // debug_message(sprintf("%O", json)); 38 | session = json["session"]; 39 | } 40 | 41 | if (stringp(session)) 42 | { 43 | socket_close(fd); 44 | debug_message("QQ_D 开始认证!"); 45 | bind(); 46 | } 47 | } 48 | 49 | private void receive_bind(int fd, mixed result) 50 | { 51 | int n = strsrch(result, "{"); 52 | // debug_message(result); 53 | if (n > 0) 54 | { 55 | mixed json; 56 | json = json_decode(trim(result[n..])); 57 | // debug_message(sprintf("%O", json)); 58 | if (!json["code"]) 59 | { 60 | socket_close(fd); 61 | debug_message("QQ_D 认证完成!"); 62 | websocket(); 63 | } 64 | } 65 | } 66 | private void receive_msg(int fd, mixed result) 67 | { 68 | // debug_message(sprintf("QQ_D receive_msg(fd = %d, result = %O)", fd, result)); 69 | socket_close(fd); 70 | } 71 | 72 | private void receive_data(int fd, mixed result) 73 | { 74 | string res; 75 | int n = strsrch(result, "{"); 76 | // debug_message("n = " + n + "\n" + result); 77 | if (n == 4 && strsrch(result, "}}}") > 0) 78 | { 79 | mixed json; 80 | mapping sender, messageChain; 81 | string type; 82 | res = trim(result[n..]); 83 | json = json_decode(res); 84 | debug_message(sprintf("%O", json)); 85 | json = json["data"]; 86 | sender = json["sender"]; 87 | type = json["type"]; 88 | // 这里只做最傻瓜的处理 89 | messageChain = json["messageChain"][1]; 90 | if (type == "GroupMessage") 91 | { 92 | string msg ="[其它类型消息]"; 93 | if (messageChain["type"] == "Plain") 94 | { 95 | msg = messageChain["text"]; 96 | } 97 | else if (messageChain["type"] == "Face") 98 | { 99 | msg = "[表情]" + messageChain["name"]; 100 | } 101 | 102 | message("chat", HIG"【QQ群】"HIC + sender["memberName"] + "@" + sender["group"]["name"] + ":" + msg, users()); 103 | } 104 | } 105 | } 106 | 107 | private void receive_callback(int fd, mixed result) 108 | { 109 | // debug_message(sprintf("QQ_D receive_callback(fd = %d, result = %O)", fd, result)); 110 | } 111 | 112 | private void socket_shutdown(int fd) 113 | { 114 | // debug_message(sprintf("QQ_D socket_shutdown(fd = %d)", fd)); 115 | socket_close(fd); 116 | } 117 | 118 | /* 游戏消息转发QQ群调用此方法 */ 119 | void msg(string msg) 120 | { 121 | int fd; 122 | int ret; 123 | string path = "/sendGroupMessage"; 124 | // string body = "{\"sessionKey\":\"" + session + "\",\"target\":" + group + ",\"messageChain\":[{\"type\":\"Plain\",\"text\":\"" + msg + "\"}]}"; 125 | // 美化格式,不用转义 126 | string body = @RAW 127 | { 128 | "sessionKey": "%^session%^", 129 | "target": %^group%^, 130 | "messageChain": [ 131 | { 132 | "type": "Plain", 133 | "text": "%^msg%^" 134 | } 135 | ] 136 | } 137 | RAW; 138 | body = terminal_colour(body, ([ 139 | "session":session, 140 | "group":group, 141 | "msg":msg, 142 | ])); 143 | 144 | fd = socket_create(STREAM, "receive_callback", "socket_shutdown"); 145 | status[fd] = ([]); 146 | status[fd]["http"] = "POST " + path + " HTTP/1.1\nHost: " + host + "\nContent-Type: application/json\nContent-Length: " + sizeof(string_encode(body, "utf-8")) + "\r\n\r\n" + body; 147 | debug_message(status[fd]["http"]); 148 | ret = socket_connect(fd, addr, "receive_msg", "http"); 149 | if (ret != EESUCCESS) 150 | { 151 | debug_message("消息服务器连接失败。\n"); 152 | socket_close(fd); 153 | } 154 | } 155 | // 连接websocket 156 | private void websocket() 157 | { 158 | int fd; 159 | int ret; 160 | string path = "/all?verifyKey=" + mirai_verifyKey + "&sessionKey=" + session; 161 | 162 | fd = socket_create(STREAM, "receive_callback", "socket_shutdown"); 163 | status[fd] = ([]); 164 | status[fd]["http"] = "GET " + path + " HTTP/1.1\nHost: " + host + "\nUpgrade: websocket\nConnection: Upgrade\r\n\r\n"; 165 | 166 | ret = socket_connect(fd, addr, "receive_data", "http"); 167 | if (ret != EESUCCESS) 168 | { 169 | debug_message("WebSocket服务器连接失败。\n"); 170 | socket_close(fd); 171 | } 172 | } 173 | // 绑定session到QQ 174 | private void bind() 175 | { 176 | int fd; 177 | int ret; 178 | string path = "/bind"; 179 | string body = "{\"sessionKey\":\"" + session + "\",\"qq\":\"" + mirai_qq + "\"}"; 180 | 181 | fd = socket_create(STREAM, "receive_callback", "socket_shutdown"); 182 | status[fd] = ([]); 183 | status[fd]["http"] = "POST " + path + " HTTP/1.1\nHost: " + host + "\nContent-Type: application/json\nContent-Length: " + strlen(body) + "\r\n\r\n" + body; 184 | // debug_message(status[fd]["http"]); 185 | ret = socket_connect(fd, addr, "receive_bind", "http"); 186 | if (ret != EESUCCESS) 187 | { 188 | debug_message("激活服务器连接失败。\n"); 189 | socket_close(fd); 190 | } 191 | } 192 | // 认证获取session 193 | private void verify() 194 | { 195 | int fd; 196 | int ret; 197 | string path = "/verify"; 198 | string body = "{\"verifyKey\":\"" + mirai_verifyKey + "\"}"; 199 | 200 | fd = socket_create(STREAM, "receive_callback", "socket_shutdown"); 201 | status[fd] = ([]); 202 | status[fd]["http"] = "POST " + path + " HTTP/1.1\nHost: " + host + "\nContent-Type: application/json\nContent-Length: " + strlen(body) + "\r\n\r\n" + body; 203 | // debug_message(status[fd]["http"]); 204 | ret = socket_connect(fd, addr, "receive_verify", "http"); 205 | if (ret != EESUCCESS) 206 | { 207 | debug_message("认证服务器连接失败。\n"); 208 | socket_close(fd); 209 | } 210 | } 211 | 212 | void create() 213 | { 214 | verify(); 215 | } 216 | -------------------------------------------------------------------------------- /system/daemons/virtual_d.c: -------------------------------------------------------------------------------- 1 | // 虚拟环境功能 2 | mixed compile_area(string file) 3 | { 4 | string virtual; 5 | object ob; 6 | int x, y, z, m, n; 7 | 8 | n = strsrch(file, "/", -1); 9 | if (n < 1) 10 | { 11 | return 0; 12 | } 13 | 14 | virtual = file[0..n - 1]; 15 | 16 | if (file_size(virtual + ".c") < 1) 17 | { 18 | return 0; 19 | } 20 | 21 | if ((m = sscanf(file[n + 1..], "%d,%d,%d", x, y, z)) != 3) 22 | { 23 | if ((m = sscanf(file[n + 1..], "%d,%d", x, y)) != 2) 24 | { 25 | return virtual->query_maze_room(file[n + 1..]); 26 | } 27 | } 28 | 29 | if (m == 2 && !(ob = new (virtual, x, y))) 30 | { 31 | return 0; 32 | } 33 | else if (m == 3 && !(ob = new (virtual, x, y, z))) 34 | { 35 | return 0; 36 | } 37 | 38 | return ob; 39 | } 40 | 41 | mixed compile_object(string str) 42 | { 43 | if (sscanf(str, "/world/%*s", str) || sscanf(str, "/home/%*s", str)) 44 | { 45 | return compile_area(str); 46 | } 47 | else 48 | { 49 | return 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /system/etc/motd: -------------------------------------------------------------------------------- 1 | $HIY$ 2 | _ _______ _______ _________ _______ _______ _________ 3 | ( \ ( ____ )( ____ \ \__ __/( ____ \( ____ \\__ __/ 4 | | ( | ( )|| ( \/ ) ( | ( \/| ( \/ ) ( 5 | | | | (____)|| | | | | (__ | (_____ | | 6 | | | | _____)| | | | | __) (_____ ) | | 7 | | | | ( | | | | | ( ) | | | 8 | | (____/\| ) | (____/\ | | | (____/\/\____) | | | 9 | (_______/|/ (_______/ )_( (_______/\_______) )_($NOR$ 10 | _\\|//_ 11 | (' . . ') 12 | ┌-----------------------------ooO-(_)-Ooo-----------------------------------┐ 13 | | ★ 欢迎光临,旅行者。 14 | | ★ 15 | | ★ LPMUD 启动文件加载顺序: 16 | | ★ 1. simul_efun (运行时配置文件中指定) 17 | | ★ 2. master (运行时配置文件中指定) 18 | | ★ 注意:所有文件都会自动#include (运行时配置文件中指定) 19 | | ★ 20 | | ★ 玩家连线流程: 21 | | ★ 1. 调用 MASTER 对象的 object connect(int port) 方法 22 | | ★ 2. 调用 object connect(int port) 方法传回对象的 object logon(void) 方法 23 | | ★ 24 | | ★ 所有对象加载时都会调用对象本身的 void create(void) 方法(如果有) 25 | └---------------------------------------------------------------------------┘ 26 | $HIG$本项目为 LPMUD 开发学习用,配套教程:https://bbs.mud.ren/threads/3$NOR$ 27 | -------------------------------------------------------------------------------- /system/etc/preload: -------------------------------------------------------------------------------- 1 | /system/object/login 2 | /system/object/user 3 | /system/object/void 4 | /system/daemons/combat_d 5 | /system/daemons/monster_d 6 | /system/daemons/virtual_d 7 | /system/daemons/qq_d 8 | -------------------------------------------------------------------------------- /system/kernel/simul_efun.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "simul_efun/color.c" 3 | #include "simul_efun/json.c" 4 | 5 | // 随机颜色输出,调试用 6 | void debug(mixed arg) 7 | { 8 | string *color = ({HIB, HIC, HIG, HIM, HIR, HIW, HIY}); 9 | 10 | debug_message(sprintf("%s%O%s", element_of(color), arg, NOR)); 11 | } 12 | 13 | void cecho(mixed arg) 14 | { 15 | string *color = ({HIB, HIC, HIG, HIM, HIR, HIW, HIY}); 16 | 17 | if (objectp(arg) || mapp(arg) || arrayp(arg)) 18 | { 19 | arg = sprintf("%O", arg); 20 | } 21 | 22 | write(element_of(color) + arg + NOR "\n"); 23 | } 24 | 25 | // 判断是否为中文 26 | int is_chinese(string str) 27 | { 28 | if (!str) 29 | return 0; 30 | 31 | return pcre_match(str, "^\\p{Han}+$"); 32 | } 33 | 34 | // 对象代称,不指定参数为返回当前玩家的代称 35 | varargs string pronoun(mixed arg, int type) 36 | { 37 | if (!objectp(arg)) 38 | { 39 | return "你"; 40 | } 41 | else 42 | { 43 | arg = arg->query("gender"); 44 | switch (type) 45 | { 46 | case 1: 47 | return "自己"; 48 | case 2: 49 | return "你"; 50 | case 3: 51 | default: 52 | switch (arg) 53 | { 54 | case "男": 55 | return "他"; 56 | case "女": 57 | return "她"; 58 | default: 59 | return "它"; 60 | } 61 | } 62 | } 63 | } 64 | 65 | // 目标广播 66 | varargs void boardcast(string type, string msg, object me, object you, object *others, object *exclude) 67 | { 68 | string my_name, my_msg, your_name, your_msg, other_msg; 69 | 70 | if (!msg || !objectp(me)) 71 | return; 72 | my_name = me->query("name") || capitalize(geteuid(me)); 73 | 74 | // 对 me 显示的消息 75 | my_msg = replace_string(msg, "$ME", pronoun()); 76 | // 对 others 显示的消息 77 | other_msg = replace_string(msg, "$ME", my_name); 78 | // 对 you 的消息处理 79 | if (objectp(you) && living(you)) 80 | { 81 | your_name = you->query("name") || capitalize(geteuid(you)); 82 | // 对 me 显示的消息 83 | my_msg = replace_string(my_msg, "$YOU", your_name, 1); 84 | my_msg = replace_string(my_msg, "$YOU", pronoun(you)); 85 | // 对 you 显示的消息 86 | your_msg = replace_string(msg, "$ME", my_name, 1); 87 | your_msg = replace_string(your_msg, "$ME", pronoun(me)); 88 | your_msg = replace_string(your_msg, "$YOU", pronoun()); 89 | // 对 others 显示的消息 90 | other_msg = replace_string(other_msg, "$YOU", your_name); 91 | // 对 you 送出信息 92 | if (!arrayp(exclude) || member_array(you, exclude) == -1) 93 | message(type, your_msg, you); 94 | } 95 | // 对 me 送出信息 96 | if (!arrayp(exclude) || member_array(me, exclude) == -1) 97 | message(type, my_msg, me); 98 | // 对其他人送出信息 99 | if (arrayp(others)) 100 | { 101 | exclude = (exclude || ({})) + (you ? ({me, you}) : ({me})); 102 | message(type, other_msg, others, exclude); 103 | } 104 | } 105 | 106 | // 区域广播 107 | varargs void msg(string type, string msg, object me, object you, object *exclude) 108 | { 109 | object *others, env = environment(me); 110 | if (env) 111 | { 112 | others = all_inventory(env); 113 | } 114 | 115 | boardcast(type, msg, me, you, others, exclude); 116 | } 117 | 118 | // 数字字符串转数字 119 | int atoi(string str) 120 | { 121 | return to_int(str); 122 | } 123 | 124 | // 数组打印 125 | varargs void print_r(mixed *arr, int step) 126 | { 127 | int i, j; 128 | if (sizeof(arr)) 129 | { 130 | write(YEL "({\n" NOR); 131 | 132 | for (i = 0; i < sizeof(arr); i++) 133 | { 134 | if (arrayp(arr[i])) 135 | { 136 | step++; 137 | for (j = 0; j < step; j++) 138 | { 139 | write(" "); 140 | } 141 | write(i + " => "); 142 | print_r(arr[i], step); 143 | step--; 144 | } 145 | else 146 | { 147 | for (j = 0; j <= step; j++) 148 | { 149 | write(" "); 150 | } 151 | // 兼容 MUDOS 152 | if (objectp(arr[i])) 153 | { 154 | arr[i] = file_name(arr[i]); 155 | } 156 | 157 | write(i + " => " + arr[i] + "\n"); 158 | } 159 | } 160 | 161 | for (j = 0; j < step; j++) 162 | { 163 | write(" "); 164 | } 165 | write(YEL "})\n" NOR); 166 | } 167 | else 168 | { 169 | write(YEL "({ })\n" NOR); 170 | } 171 | } 172 | 173 | //检查state的第pos位是否为1 174 | int bitCheck(int state, int pos) 175 | { 176 | return state & (1 << (pos - 1)); 177 | } 178 | 179 | //将state的第pos位的值设为1 180 | int bitSet(int state, int pos) 181 | { 182 | return state | (1 << (pos - 1)); 183 | } 184 | 185 | //将state的第pos位的值设为0 186 | int bitClear(int state, int pos) 187 | { 188 | return state & (~(1 << (pos - 1))); 189 | } 190 | 191 | // 读取文件按行返回数组 192 | string *read_config(string file) 193 | { 194 | string str = read_file(file); 195 | 196 | if (!str) 197 | return ({}); 198 | 199 | return filter_array( 200 | explode(str, "\n"), function(string line) { 201 | if (trim(line) == "" || line[0] == '#' || line[0] == ';') 202 | { 203 | return 0; 204 | } 205 | 206 | return 1; 207 | }); 208 | } 209 | -------------------------------------------------------------------------------- /system/kernel/simul_efun/color.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright: 2019, Mud.Ren 3 | File name: color.c 4 | Description: ANSI颜色处理相关模拟函数 5 | Author: xuefeng 6 | Version: v1.0 7 | Date: 2019-03-12 8 | *****************************************************************************/ 9 | #include 10 | // 清理ansi色彩 11 | string remove_ansi(string arg) 12 | { 13 | arg = replace_string(arg, BLK, ""); 14 | arg = replace_string(arg, RED, ""); 15 | arg = replace_string(arg, GRN, ""); 16 | arg = replace_string(arg, YEL, ""); 17 | arg = replace_string(arg, BLU, ""); 18 | arg = replace_string(arg, MAG, ""); 19 | arg = replace_string(arg, CYN, ""); 20 | arg = replace_string(arg, WHT, ""); 21 | arg = replace_string(arg, HIR, ""); 22 | arg = replace_string(arg, HIG, ""); 23 | arg = replace_string(arg, HIY, ""); 24 | arg = replace_string(arg, HIB, ""); 25 | arg = replace_string(arg, HIM, ""); 26 | arg = replace_string(arg, HIC, ""); 27 | arg = replace_string(arg, HIW, ""); 28 | arg = replace_string(arg, NOR, ""); 29 | arg = replace_string(arg, BOLD, ""); 30 | arg = replace_string(arg, BLINK, ""); 31 | arg = replace_string(arg, BBLK, ""); 32 | arg = replace_string(arg, BRED, ""); 33 | arg = replace_string(arg, BGRN, ""); 34 | arg = replace_string(arg, BYEL, ""); 35 | arg = replace_string(arg, BBLU, ""); 36 | arg = replace_string(arg, BMAG, ""); 37 | arg = replace_string(arg, BCYN, ""); 38 | arg = replace_string(arg, HBRED, ""); 39 | arg = replace_string(arg, HBGRN, ""); 40 | arg = replace_string(arg, HBYEL, ""); 41 | arg = replace_string(arg, HBBLU, ""); 42 | arg = replace_string(arg, HBMAG, ""); 43 | arg = replace_string(arg, HBCYN, ""); 44 | arg = replace_string(arg, HBWHT, ""); 45 | return arg; 46 | } 47 | 48 | // 增加色彩输出 49 | string ansi(string content) 50 | { 51 | if (!content) 52 | return ""; 53 | 54 | // Foreground color 55 | content = replace_string(content, "$BLK$", BLK); 56 | content = replace_string(content, "$RED$", RED); 57 | content = replace_string(content, "$GRN$", GRN); 58 | content = replace_string(content, "$YEL$", YEL); 59 | content = replace_string(content, "$BLU$", BLU); 60 | content = replace_string(content, "$MAG$", MAG); 61 | content = replace_string(content, "$CYN$", CYN); 62 | content = replace_string(content, "$WHT$", WHT); 63 | content = replace_string(content, "$HIR$", HIR); 64 | content = replace_string(content, "$HIG$", HIG); 65 | content = replace_string(content, "$HIY$", HIY); 66 | content = replace_string(content, "$HIB$", HIB); 67 | content = replace_string(content, "$HIM$", HIM); 68 | content = replace_string(content, "$HIC$", HIC); 69 | content = replace_string(content, "$HIW$", HIW); 70 | content = replace_string(content, "$NOR$", NOR); 71 | 72 | // Background color 73 | content = replace_string(content, "$BBLK$", BBLK); 74 | content = replace_string(content, "$BRED$", BRED); 75 | content = replace_string(content, "$BGRN$", BGRN); 76 | content = replace_string(content, "$BYEL$", BYEL); 77 | content = replace_string(content, "$BBLU$", BBLU); 78 | content = replace_string(content, "$BMAG$", BMAG); 79 | content = replace_string(content, "$BCYN$", BCYN); 80 | content = replace_string(content, "$HBRED$", HBRED); 81 | content = replace_string(content, "$HBGRN$", HBGRN); 82 | content = replace_string(content, "$HBYEL$", HBYEL); 83 | content = replace_string(content, "$HBBLU$", HBBLU); 84 | content = replace_string(content, "$HBMAG$", HBMAG); 85 | content = replace_string(content, "$HBCYN$", HBCYN); 86 | 87 | content = replace_string(content, "$U$", U); 88 | content = replace_string(content, "$BLINK$", BLINK); 89 | content = replace_string(content, "$REV$", REV); 90 | content = replace_string(content, "$HIREV$", HIREV); 91 | content = replace_string(content, "$BOLD$", BOLD); 92 | 93 | return content; 94 | } 95 | 96 | void color_cat(string file) 97 | { 98 | write(ansi(read_file(file))); 99 | } 100 | 101 | // calculate the color char in a string 102 | int color_len(string str) 103 | { 104 | int i, extra; 105 | 106 | extra = 0; 107 | for (i = 0; i < strlen(str); i++) 108 | { 109 | if (str[i] == ESC[0]) 110 | { 111 | while ((extra++, str[i] != 'm') && i < strlen(str)) 112 | i++; 113 | } 114 | } 115 | return extra; 116 | } 117 | -------------------------------------------------------------------------------- /system/object/login.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright: 2019, Mud.Ren 3 | File name: login_ob.c 4 | Description: 玩家登录连线对象 5 | Author: xuefeng 6 | Version: v1.0 7 | Date: 2019-04-18 8 | *****************************************************************************/ 9 | #define WELCOME "/system/etc/motd" 10 | 11 | void setup(string arg) 12 | { 13 | object from, to; 14 | 15 | if (!arg || arg == "") 16 | { 17 | write("ID不能为空,请重新输入:"); 18 | input_to("setup"); 19 | } 20 | else 21 | { 22 | from = this_object(); 23 | to = new(USER_OB, arg); 24 | exec(to, from); 25 | destruct(from); 26 | // log 27 | debug_message(ctime() + " " + query_ip_number(to) + " " + arg); 28 | } 29 | } 30 | 31 | void logon() 32 | { 33 | color_cat(WELCOME); 34 | write("请输入你的ID:"); 35 | input_to("setup"); 36 | } 37 | 38 | void net_dead() 39 | { 40 | debug_message(ctime() + " net_dead " + query_ip_number()); 41 | destruct(); 42 | } 43 | -------------------------------------------------------------------------------- /system/object/user.c: -------------------------------------------------------------------------------- 1 | #define CMD_PATH "/cmds/cmd/" 2 | #define DEMO_PATH "/cmds/demo/" 3 | #define TEST_PATH "/cmds/test/" 4 | 5 | varargs void create(string arg) 6 | { 7 | if (clonep()) 8 | { 9 | enable_commands(); 10 | add_action("command_hook", "", 1); 11 | seteuid(arg); 12 | set_living_name(arg); 13 | move_object(VOID_OB); 14 | } 15 | } 16 | 17 | int command_hook(string arg) 18 | { 19 | string verb, cmd, demo, test; 20 | object cmd_ob; 21 | 22 | verb = query_verb(); 23 | cmd = CMD_PATH + verb; 24 | demo = DEMO_PATH + verb; 25 | test = TEST_PATH + verb; 26 | 27 | if (cmd_ob = load_object(cmd) || cmd_ob = load_object(test) || cmd_ob = load_object(demo)) 28 | { 29 | return (int)cmd_ob->main(this_object(), arg); 30 | } 31 | else 32 | { 33 | return notify_fail("指令不存在,你可以输入 tutorial 寻求帮助。\n"); 34 | } 35 | } 36 | 37 | void net_dead() 38 | { 39 | destruct(); 40 | } 41 | -------------------------------------------------------------------------------- /system/object/void.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluffos/lpc-test/0b32105eff1aaee0496cf044c3bef723a674d3f9/system/object/void.c -------------------------------------------------------------------------------- /tmp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /verbs/fight.c: -------------------------------------------------------------------------------- 1 | inherit VERB; 2 | 3 | #include 4 | 5 | protected void create() 6 | { 7 | verb::create(); 8 | setVerb("fight"); 9 | setSynonyms("kill", "hit"); 10 | setRules("LIV"); 11 | setErrorMessage("你想和谁战斗?"); 12 | } 13 | 14 | mixed can_fight_liv(mixed *data...) 15 | { 16 | object me = this_player(); 17 | // cecho(data); 18 | if (file_name(environment(me)) == START_ROOM) 19 | { 20 | return "这里禁止战斗。"; 21 | } 22 | return me->can_fight() || HIY "你无法战斗。" NOR; 23 | } 24 | 25 | mixed direct_fight_liv(object ob, string arg) 26 | { 27 | if (ob == this_player()) 28 | return HIM "你真有想法,可惜你做不到自己和自己战斗。" NOR; 29 | return ob->can_fight(); 30 | } 31 | 32 | int do_fight_liv(object ob, string arg) 33 | { 34 | object me = this_player(); 35 | 36 | msg("warning", "$ME大喝一声,对$YOU发起了攻击。", me, ob); 37 | me->fight(ob); 38 | 39 | return 1; 40 | } 41 | 42 | int help(object me) 43 | { 44 | write(@HELP 45 | 指令格式 : fight | hit | kill 46 | 47 | 战斗指令,可以向其它生物发起战斗。 48 | 49 | HELP ); 50 | return 1; 51 | } 52 | -------------------------------------------------------------------------------- /verbs/go.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 雪风@mud.ren 3 | * @Date: 2022-04-02 17:41:08 4 | * @LastEditTime: 2022-04-02 20:23:11 5 | * @LastEditors: 雪风 6 | * @Description: 7 | * https://bbs.mud.ren 8 | */ 9 | inherit VERB; 10 | 11 | #include 12 | #include 13 | 14 | protected void create() 15 | { 16 | verb::create(); 17 | setVerb("go"); 18 | setSynonyms("move"); 19 | setRules("STR", "into STR"); 20 | setErrorMessage("你想去哪儿?"); 21 | } 22 | 23 | mixed can_go_str(string dir, string str) 24 | { 25 | object me = this_player(); 26 | object env = environment(me); 27 | object dest; 28 | mapping exits; 29 | mixed exit; 30 | 31 | if (!me->query("area_info") && (!mapp(exits = env->query("exits")) || undefinedp(exit = exits[dir]))) 32 | { 33 | return RED "这个方向没有出路。" NOR; 34 | } 35 | 36 | if (me->is_fighting()) 37 | { 38 | return YEL "你逃跑失败了~" NOR; 39 | } 40 | 41 | switch (typeof(exit)) 42 | { 43 | case T_STRING: 44 | if (!objectp(dest = load_object(exit))) 45 | { 46 | return sprintf("目标环境异常,无法向 %s 移动。", exit); 47 | } 48 | break; 49 | case T_MAPPING: 50 | if (undefinedp(exit["filename"]) || undefinedp(exit["x_axis"]) || undefinedp(exit["y_axis"])) 51 | { 52 | return sprintf("目标方向异常,无法向 %s 移动。", dir); 53 | } 54 | if (!objectp(dest = load_object(exit["filename"]))) 55 | { 56 | return sprintf("目标环境异常,无法向 %s 移动。\n", exit["filename"]); 57 | } 58 | break; 59 | default: 60 | return env->is_area() || "这个方向的出口有问题,请联系巫师处理。"; 61 | } 62 | 63 | return 1; 64 | } 65 | 66 | int do_go_str(string dir, string str) 67 | { 68 | object me = this_player(); 69 | object env = environment(me); 70 | mapping exits = env->query("exits"); 71 | mixed exit; 72 | object dest; 73 | 74 | if (env->is_area()) 75 | return env->area_go(me, dir); 76 | 77 | exit = exits[dir]; 78 | dest = stringp(exit) ? load_object(exit) : load_object(exit["filename"]); 79 | 80 | if (dest->is_area()) 81 | { 82 | dest->area_move(me, exit["x_axis"], exit["y_axis"]); 83 | } 84 | else 85 | { 86 | msg("info", "$ME离开了这里!", me, environment(me), ({me})); 87 | me->move(dest); 88 | msg("info", "$ME走了过了!", me, environment(me), ({me})); 89 | } 90 | 91 | return 1; 92 | } 93 | -------------------------------------------------------------------------------- /verbs/look.c: -------------------------------------------------------------------------------- 1 | inherit VERB; 2 | 3 | #include 4 | 5 | int look_room(object me, object env); 6 | string desc_of_objects(object *obs); 7 | string list_all_inventory_of_object(object me, object env); 8 | int look_living(object me, object ob); 9 | 10 | protected void create() 11 | { 12 | verb::create(); 13 | setVerb("look"); 14 | setSynonyms("l"); 15 | setRules("", "STR", "OBJ", "at STR", "at OBJ", "on OBJ", "in OBJ", "inside OBJ", 16 | "at OBJ in OBJ", "OBJ inside OBJ", "at OBJ on OBJ", "at STR on OBJ"); 17 | setErrorMessage("你想看什么?"); 18 | } 19 | 20 | mixed can_look() 21 | { 22 | object env = environment(this_player()); 23 | if (!env || !env->query("short") && !env->is_area()) 24 | return "你的四周灰蒙蒙地一片,什么也没有。"; 25 | else 26 | return 1; 27 | } 28 | 29 | mixed can_verb_rule(mixed *data...) 30 | { 31 | // debug_message(sprintf("can_verb_rule : %O", data)); 32 | return can_look(); 33 | } 34 | 35 | mixed can_verb_word_str(mixed *data...) 36 | { 37 | // debug_message(sprintf("can_verb_word_str : %O", data)); 38 | return can_look(); 39 | } 40 | 41 | mixed direct_look_obj(object ob, string id) 42 | { 43 | return environment(this_player()) == environment(ob); 44 | } 45 | 46 | mixed direct_verb_rule(mixed *data...) 47 | { 48 | // debug_message(sprintf("direct_verb_rule : %O", data)); 49 | return can_look(); 50 | } 51 | 52 | mixed direct_verb_word_obj(mixed *data...) 53 | { 54 | // debug_message(sprintf("direct_verb_word_obj : %O", data)); 55 | return can_look(); 56 | } 57 | 58 | mixed do_look() 59 | { 60 | object me = this_player(); 61 | object env = environment(me); 62 | 63 | return look_room(me, env); 64 | } 65 | 66 | mixed do_look_at_obj(object ob) 67 | { 68 | object me = this_player(); 69 | 70 | if (living(ob)) 71 | { 72 | look_living(me, ob); 73 | } 74 | else 75 | { 76 | printf("%s\n", ob->long()); 77 | } 78 | 79 | return 1; 80 | } 81 | 82 | mixed do_look_at_obj_in_obj(object ob1, object ob2, string id1, string id2) 83 | { 84 | printf("%s\n", ob1->long()); 85 | return 1; 86 | } 87 | 88 | mixed do_look_obj(object ob) 89 | { 90 | return do_look_at_obj(ob); 91 | } 92 | 93 | mixed do_look_in_obj(object ob) 94 | { 95 | if (sizeof(all_inventory(ob))) 96 | { 97 | cecho(sprintf("%s里有:\n%s", ob->short(), list_all_inventory_of_object(ob, ob))); 98 | } 99 | else 100 | { 101 | cecho(sprintf("%s里什么也没有。", ob->short())); 102 | } 103 | 104 | return 1; 105 | } 106 | 107 | mixed do_look_at_str(string str, string arg) 108 | { 109 | object me = this_player(); 110 | object env = environment(me); 111 | mapping exits = env->query("exits"); 112 | object ob; 113 | mixed item_desc; 114 | 115 | if (str == "here") 116 | { 117 | return do_look(); 118 | } 119 | else if (stringp(exits[str])) 120 | return look_room(me, load_object(exits[str])); 121 | else if (mapp(exits[str])) 122 | cecho("此方向是区域环境,无法观察。"); 123 | else if (item_desc = env->query("items/" + str)) 124 | cecho(evaluate(item_desc)); 125 | else if (ob = present(arg, env)) 126 | return do_look_obj(ob); 127 | else 128 | cecho(getErrorMessage()); 129 | 130 | return 1; 131 | } 132 | 133 | mixed do_look_str(string str, string arg) 134 | { 135 | return do_look_at_str(str, arg); 136 | } 137 | 138 | mixed do_verb_rule(mixed *data...) 139 | { 140 | cecho(sprintf("do_verb_rule : %O", data)); 141 | return 1; 142 | } 143 | 144 | // 查看环境(此方法推荐放在环境中) 145 | int look_room(object me, object env) 146 | { 147 | string str, *dirs; 148 | mapping exits; 149 | 150 | if (env->is_area()) 151 | { 152 | return env->do_look(me); 153 | } 154 | 155 | str = sprintf(HIC + "%s" + NOR + " <%s>\n%s" + NOR, 156 | env->query("short"), file_name(env), env->query("long")); 157 | 158 | if (mapp(exits = env->query("exits"))) 159 | { 160 | dirs = keys(exits); 161 | 162 | if (sizeof(dirs) == 0) 163 | str += " 这里没有任何明显的出路。\n"; 164 | else if (sizeof(dirs) == 1) 165 | str += " 这里唯一的出口是 " + BOLD + dirs[0] + NOR + "。\n"; 166 | else 167 | str += sprintf(" 这里明显的出口是 " + BOLD + "%s" + NOR + " 和 " + BOLD + "%s" + NOR + "。\n", 168 | implode(dirs[0..sizeof(dirs)-2], "、"), dirs[sizeof(dirs) - 1]); 169 | } 170 | else 171 | { 172 | str += " 这里没有任何出路。\n"; 173 | } 174 | str += list_all_inventory_of_object(me, env); 175 | tell_object(me, str); 176 | return 1; 177 | } 178 | 179 | string desc_of_objects(object *obs) 180 | { 181 | int i; 182 | string str; 183 | mapping list, unit; 184 | string short_name; 185 | string *ob; 186 | 187 | if (obs && sizeof(obs) > 0) 188 | { 189 | str = ""; 190 | list = ([]); 191 | unit = ([]); 192 | 193 | for (i = 0; i < sizeof(obs); i++) 194 | { 195 | short_name = obs[i]->short(); 196 | 197 | list[short_name] += obs[i]->query_temp("amount") ? obs[i]->query_temp("amount") : 1; 198 | unit[short_name] = obs[i]->query("unit") ? obs[i]->query("unit") : "个"; 199 | } 200 | 201 | ob = sort_array(keys(list), 1); 202 | for (i = 0; i < sizeof(ob); i++) 203 | { 204 | str += " "; 205 | if (list[ob[i]] > 1) 206 | str += list[ob[i]] + unit[ob[i]] + ob[i] + "\n"; 207 | else 208 | str += ob[i] + "\n"; 209 | } 210 | return str; 211 | } 212 | 213 | return ""; 214 | } 215 | 216 | string list_all_inventory_of_object(object me, object env) 217 | { 218 | object *inv; 219 | object *obs; 220 | string str = ""; 221 | 222 | if (!env || !me) 223 | return ""; 224 | 225 | inv = all_inventory(env); 226 | if (!sizeof(inv)) 227 | return str; 228 | 229 | obs = filter_array(inv, (: $(me) != $1 :)); 230 | str += desc_of_objects(obs); 231 | 232 | return str; 233 | } 234 | 235 | int look_living(object me, object ob) 236 | { 237 | string msg; 238 | string line = repeat_string("-*-", 12) + "\n"; 239 | 240 | if (ob != this_player()) 241 | { 242 | msg = "$ME看了看$YOU,好像对$YOU很感兴趣对样子。"; 243 | msg("vision", msg, me, ob); 244 | } 245 | msg = sprintf("%s 是一位 %d 级的%s性生物。\n", ob->short(), ob->query("lv"), ob->query("gender") || "??"); 246 | msg += line; 247 | msg += sprintf(" %-36s\n", "HP:" + ob->query("hp") + " / " + ob->query("max_hp")); 248 | msg += sprintf(" %-12s%-12s%-12s\n", "力量:" + ob->query("str"), "敏捷:" + ob->query("agi"), "防御:" + ob->query("def")); 249 | msg += line; 250 | tell_object(me, msg); 251 | 252 | return 1; 253 | } 254 | 255 | int help(object me) 256 | { 257 | write(@HELP 258 | 指令格式 : look | l 259 | 260 | 最基本的look指令,让你睁眼看世界,可以查看对象了解信息。 261 | 262 | 当存在多个同名对象时,比如有4个NPC,你要查看指定对象可以使用以下格式: 263 | 264 | l 1st n 或 l n 1 265 | l 2nd n 或 l n 2 266 | l 3rd n 或 l n 3 267 | l 4th n 或 l n 4 268 | 269 | HELP ); 270 | return 1; 271 | } 272 | -------------------------------------------------------------------------------- /world/.gitignore: -------------------------------------------------------------------------------- 1 | maze.map 2 | -------------------------------------------------------------------------------- /world/area.c: -------------------------------------------------------------------------------- 1 | inherit AREA; 2 | 3 | void create() 4 | { 5 | set("name", "我的世界"); 6 | set("x_axis_size", 25); // 橫向大小 7 | set("y_axis_size", 15); // 縱向大小 8 | setup(); 9 | } 10 | -------------------------------------------------------------------------------- /world/area.o: -------------------------------------------------------------------------------- 1 | #/world/area.c 2 | dbase (["x_axis_size":25,"name":"我的世界","file_path":"/world/","y_axis_size":15,]) 3 | area ({({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),(["icon":"⛺",]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),(["icon":"🌲",]),([]),(["block":1,"icon":" ",]),(["block":1,"icon":" ",]),(["block":1,"icon":" ",]),(["block":1,"icon":" ",]),(["block":1,"icon":" ",]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),(["block":1,"icon":"  ",]),(["icon":"下",]),(["icon":"午",]),(["icon":"镇",]),(["block":1,"icon":"  ",]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),(["icon":"🌴",]),([]),(["block":1,"icon":" ",]),(["block":1,"icon":" ",]),(["icon":"__","room_exit":"__DIR__world/0,0,0",]),(["block":1,"icon":" ",]),(["block":1,"icon":" ",]),([]),([]),(["icon":"🕳️ ",]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),(["icon":"🌲",]),([]),([]),([]),([]),(["icon":"🌴",]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),(["loads":(["__DIR__world/npc/npc":3,]),]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),(["icon":"🌀",]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),({([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),([]),}),}) 4 | LOLO ({"10,10",}) 5 | -------------------------------------------------------------------------------- /world/maze.c: -------------------------------------------------------------------------------- 1 | // 迷宫 2 | #include 3 | inherit MAZE; 4 | 5 | void create() 6 | { 7 | //迷宫房间所继承的物件的档案名称 8 | set_inherit_room( ROOM ); 9 | 10 | //迷宫房间里的怪物 11 | set_maze_npcs(({__DIR__ "world/npc/mob"})); 12 | 13 | //迷宫的单边长 14 | set_maze_long(10); 15 | 16 | //入口方向(出口在对面) 17 | set_entry_dir("south"); 18 | 19 | //入口与区域的连接方向 20 | set_link_entry_dir("south"); 21 | 22 | //入口与区域的连接档案名 23 | set_link_entry_room(__DIR__"world/5,2,0"); 24 | 25 | //出口与区域的连接方向 26 | set_link_exit_dir("enter"); 27 | 28 | //出口与区域的连接档案名 29 | set_link_exit_room(__DIR__"tower"); 30 | 31 | //入口房间短描述 32 | set_entry_short(HIY "巨人王庭入口" NOR); 33 | 34 | //入口房间描述 35 | set_entry_desc(YEL @LONG 36 | 这里是巨人王庭宫殿遗迹的入口,这里永远处于黄昏状态,那黄昏的光芒宛若实质,覆盖在宫殿表面,带来了强烈的衰败感。 37 | LONG NOR); 38 | 39 | //出口房间短描述 40 | set_exit_short(HIY "巨人王庭出口" NOR); 41 | 42 | //出口房间描述 43 | set_exit_desc(HIW @LONG 44 | 你眼前一亮,深深的吸了口气,心想总算是出来了。不过景色忽的一变,眼前出现一座高耸入云的魔法塔。 45 | LONG NOR); 46 | 47 | //迷宫房间的短描述 48 | set_maze_room_short(HIB "巨人王庭" NOR); 49 | 50 | //迷宫房间的描述,如果有多条描述,制造每个房间的时候会从中随机选择一个。 51 | set_maze_room_desc(HIB @LONG 52 | 这里是巨人王庭内部,因为真神的影响,绝大部分力量都明显衰退了,只有被神国承认的守卫,才能发挥相对正常的水准。 53 | LONG NOR); 54 | 55 | // 迷宫房间是否为户外房间? 56 | // set_outdoors(1); 57 | 58 | // 是否绘制迷宫地图? 59 | set_maze_map(1); 60 | 61 | // 迷宫的额外参数 62 | set_extra_info(([ 63 | ])); 64 | } 65 | -------------------------------------------------------------------------------- /world/maze/5-5.c: -------------------------------------------------------------------------------- 1 | inherit DBASE; 2 | 3 | void create() 4 | { 5 | object ob = new ("/world/world/npc/mob", 9, 99); 6 | ob->move(this_object()); 7 | 8 | set("short", "巨人王庭大厅"); 9 | set("long", @LONG 10 | 这里是巨人王庭内部大厅,一位强大的暗天使恶灵在这里守护着传说中的亵渎石板。 11 | LONG ); 12 | set("exits", ([ 13 | "east":__DIR__ "6-5", 14 | "north":__DIR__ "5-6", 15 | "south":__DIR__ "5-4", 16 | "west":__DIR__ "4-5", 17 | ])); 18 | } 19 | -------------------------------------------------------------------------------- /world/tower.c: -------------------------------------------------------------------------------- 1 | // tower.c 2 | inherit CLEAN_UP; 3 | inherit DBASE; 4 | 5 | varargs void create(int x, int y, int z) 6 | { 7 | set("short", "勇者之塔 第 " + z + " 层"); 8 | set("long", @LONG 9 | 这里是封印着无穷无尽的魔物的勇者之塔,据说这座塔通天彻地,没有人知道具体有多少层,也没有人真正的到达过终点。 10 | LONG); 11 | set("exits", ([ 12 | "up":__DIR__ "tower/" + x + "," + y + "," + (z + 1), 13 | "down":__DIR__ "tower/" + x + "," + y + "," + (z - 1), 14 | ])); 15 | 16 | if (z) 17 | { 18 | object ob = new (__DIR__ "world/npc/mob", z); 19 | ob->move(this_object()); 20 | } 21 | else 22 | { 23 | delete("exits/down"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /world/world.c: -------------------------------------------------------------------------------- 1 | // world.c 2 | inherit ROOM; 3 | 4 | varargs void create(int x, int y, int z) 5 | { 6 | if (x > -3 && x < 3 && y > -3 && y < 3) 7 | { 8 | set("short", "下午镇 - 坐标(" + x + "," + y + "," + z + ")"); 9 | set("long", @LONG 10 | 这里是下午镇废墟,曾经的居民早已不知去向,只有不变的黑夜和潜藏的危险。 11 | LONG); 12 | } 13 | else 14 | { 15 | set("short", "神弃之地 - 坐标(" + x + "," + y + "," + z + ")"); 16 | set("long", @LONG 17 | 这里是被众神遗弃的地方,这里的天空没有太阳,没有月亮,没有星星,只有不变的黑夜和撕裂着一切的闪电。 18 | LONG); 19 | set("objects", ([__DIR__ "world/npc/mob" : random(3),])); 20 | setup(); 21 | } 22 | 23 | set("exits", ([ 24 | "north":__DIR__ "world/" + x + "," + (y + 1) + "," + z, 25 | "south":__DIR__ "world/" + x + "," + (y - 1) + "," + z, 26 | "west":__DIR__ "world/" + (x - 1) + "," + y + "," + z, 27 | "east":__DIR__ "world/" + (x + 1) + "," + y + "," + z, 28 | ])); 29 | // 一定机率移除随机出口 30 | if (!random(3)) 31 | { 32 | removeRandomExit(); 33 | } 34 | } 35 | 36 | void virtual_start() 37 | { 38 | set("objects", ([__DIR__ "world/npc/npc" : random(5),])); 39 | setup(); 40 | } 41 | -------------------------------------------------------------------------------- /world/world/0,0,0.c: -------------------------------------------------------------------------------- 1 | // 0,0,0.c 2 | inherit DBASE; 3 | 4 | string look_door(); 5 | 6 | void create() 7 | { 8 | set("short", "下午镇营地"); 9 | set("long", @LONG 10 | 这里是白银城冒险者清理过的下午镇营地,微弱的篝火照亮了黑暗。远处篝火无法照亮的黑暗里潜藏着无尽的危险。 11 | 这里还有一个传送门(door),使用它可以传送到一个特别的世界。 12 | LONG ); 13 | set("exits", ([ 14 | "east":__DIR__ "1,0,0", 15 | "north":__DIR__ "0,1,0", 16 | "south":__DIR__ "0,-1,0", 17 | "west":__DIR__ "-1,0,0", 18 | ])); 19 | set("items", ([ 20 | "door" : (: look_door :), 21 | ])); 22 | } 23 | 24 | void init() 25 | { 26 | add_action(function(string arg) { 27 | object me = this_player(); 28 | if (me->query_temp("step") < 3) 29 | return notify_fail("你当前状态无法传送,输入 tutorial 3 后方可使用此传送门。\n"); 30 | me->msp_oob("!!MUSIC(1001.mp3 L=1 V=100 U=https://mud.ren/storage/wav/)"); 31 | return me->move("/world/area"); 32 | }, ({"in", "enter"})); 33 | } 34 | 35 | string look_door() 36 | { 37 | object me = this_player(); 38 | 39 | if (me->query_temp("step") < 3) 40 | return "这个传送门闪着微光,还在蓄积能量中,暂时无法传送(in)。"; 41 | else 42 | return "这个传送门闪着耀眼的光芒,你可以试试传送(in)功能。"; 43 | } 44 | -------------------------------------------------------------------------------- /world/world/5,2,0.c: -------------------------------------------------------------------------------- 1 | // 5.2.0.c 2 | inherit ROOM; 3 | 4 | void create() 5 | { 6 | set("short", "神弃之地 - 坐标(5,2,0)"); 7 | set("long", @LONG 8 | 这里是下午镇郊外,几位提着兽皮灯笼的白银城冒险者正在这里探索,向北是巨人王庭遗迹的入口。 9 | LONG ); 10 | set("objects",([ 11 | __DIR__ "npc/npc" : 1 + random(3), 12 | ])); 13 | set("exits", ([ 14 | "east":__DIR__ "6,2,0", 15 | "north": "/world/maze/entry", 16 | "south":__DIR__ "5,1,0", 17 | "west":__DIR__ "4,2,0", 18 | ])); 19 | setup(); 20 | } 21 | -------------------------------------------------------------------------------- /world/world/npc/mob.c: -------------------------------------------------------------------------------- 1 | inherit COMBAT; 2 | inherit LIVING; 3 | 4 | varargs void create(int i, int lv) 5 | { 6 | mixed info; 7 | ::create(); 8 | if (nullp(i)) 9 | { 10 | i = 1 + random(7); 11 | } 12 | lv = lv || 1 + random(i * 10); 13 | info = MONSTER_D->info(i); 14 | set_living(info[0]); 15 | set("name", info[1]); 16 | set("unit", "位"); 17 | set("lv", lv); 18 | if (clonep()) 19 | { 20 | set("max_hp", info[2] + info[2] * lv / 10); 21 | set("hp", query("max_hp")); 22 | set("str", info[3] + info[3] * lv / 10); 23 | set("def", info[4] + info[4] * lv / 10); 24 | set("agi", info[5] + info[5] * lv / 10); 25 | 26 | set_heart_beat(1); 27 | } 28 | } 29 | 30 | void init() 31 | { 32 | object me = this_player(); 33 | 34 | if (interactive(me) && me->can_fight()) 35 | { 36 | object ob = query_shadowing(this_object()) || this_object(); 37 | ob->fight(me); 38 | } 39 | } 40 | 41 | object shadowto(object ob) 42 | { 43 | set_living(geteuid(ob)); 44 | return shadow(ob, 1); 45 | } 46 | -------------------------------------------------------------------------------- /world/world/npc/npc.c: -------------------------------------------------------------------------------- 1 | inherit COMBAT; 2 | inherit LIVING; 3 | 4 | void create() 5 | { 6 | ::create(); 7 | set_living("npc"); 8 | set("name", "白银城冒险者"); 9 | set("unit", "位"); 10 | if (clonep()) 11 | { 12 | int lv = random(100) + 1; 13 | set("lv", lv); 14 | set("max_hp", 5 * lv + random(50)); 15 | set("hp", query("max_hp")); 16 | set("str", 4 * lv + random(40)); 17 | set("def", 3 * lv + random(30)); 18 | set("agi", 2 * lv + random(20)); 19 | set("gender", random(2) ? "男" : "女"); 20 | set_heart_beat(1); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /www/css/xterm.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using clean-css v5.3.1. 3 | * Original file: /npm/xterm@5.1.0/css/xterm.css 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | .xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:0}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm .xterm-cursor-pointer,.xterm.xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;z-index:10;color:transparent}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-decoration-overview-ruler{z-index:7;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative} 8 | /*# sourceMappingURL=/sm/ed9fedfab875786b71d458ce8b7f61fb32907751329bb598370b74f2f4f02efa.map */ -------------------------------------------------------------------------------- /www/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluffos/lpc-test/0b32105eff1aaee0496cf044c3bef723a674d3f9/www/favicon.ico -------------------------------------------------------------------------------- /www/font/NotoSansMono-VariableFont_wdth,wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluffos/lpc-test/0b32105eff1aaee0496cf044c3bef723a674d3f9/www/font/NotoSansMono-VariableFont_wdth,wght.ttf -------------------------------------------------------------------------------- /www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | Lpc-Test@mud.ren 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 38 | 39 | 40 | 41 |
42 |
43 | 44 |
45 |
46 |
47 |
48 |
49 | 50 | 51 |
52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /www/js/main.js: -------------------------------------------------------------------------------- 1 | // 基于xterm.js的websocket通信 2 | 3 | function isMobile() { 4 | const userAgent = navigator.userAgent || navigator.vendor || window.opera; 5 | const mobiles = ["windows phone", "android", "iPhone", "iPad", "iPod"]; 6 | for (let i = 0; i < mobiles.length; i++) { 7 | if (new RegExp(mobiles[i], "i").test(userAgent)) { 8 | return true; 9 | } 10 | } 11 | return false; 12 | } 13 | 14 | const WebFontSize = 14; 15 | const MobileFontSize = 9; 16 | const term = new Terminal({ 17 | convertEol: true, 18 | disableStdin: true, 19 | allowProposedApi: true, 20 | fontSize: isMobile() ? MobileFontSize : WebFontSize 21 | }); 22 | const unicode14Addon = new Unicode14Addon(true); 23 | const weblinksAddon = new WebLinksAddon.WebLinksAddon(); 24 | const fitAddon = new FitAddon.FitAddon(); 25 | term.loadAddon(unicode14Addon); 26 | term.unicode.activeVersion = '14'; 27 | term.loadAddon(weblinksAddon); 28 | term.loadAddon(fitAddon); 29 | 30 | document.addEventListener("DOMContentLoaded", () => { 31 | // 玩家输入指令 32 | const cmd = document.getElementById("cmd"); 33 | // 指令发送按钮 34 | const send = document.getElementById("send"); 35 | // 按键事件 36 | cmd.addEventListener("keydown", (e) => { 37 | switch (e.key) { 38 | case "Enter": 39 | sendCmd(); 40 | break; 41 | case "ArrowUp": 42 | getCmd1(); 43 | break; 44 | case "ArrowDown": 45 | getCmd2(); 46 | break; 47 | } 48 | }); 49 | 50 | const container = document.getElementById('container') 51 | container.style.height = "90vh"; 52 | // Open the terminal in terminal-container 53 | term.open(container); 54 | // Make the terminal's size and geometry fit the size of terminal-container 55 | fitAddon.fit(); 56 | }); 57 | window.addEventListener('resize', fitAddon.fit); 58 | 59 | let ws = null 60 | // 取得websocket地址 61 | function getWsUrl(extra_url) { 62 | const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://'; 63 | const host = window.location.host; 64 | return `${protocol}${host}/${extra_url}`; 65 | } 66 | // 连接游戏 67 | function mudConnect() { 68 | if ("WebSocket" in window) { 69 | let url = getWsUrl(); 70 | // 打开一个 web socket 71 | ws = new WebSocket(url, "ascii"); 72 | const attachAddon = new AttachAddon.AttachAddon(ws); 73 | term.loadAddon(attachAddon); 74 | ws.onopen = (_event) => { 75 | console.log("服务器连接成功!"); 76 | cmd.focus(); 77 | }; 78 | ws.onclose = (_event) => { 79 | console.log("服务器连接断开!"); 80 | term.write("\r\n<======== Connection Lost ========>\r\n"); 81 | send.setAttribute("disabled", "disabled"); 82 | cmd.setAttribute("disabled", "disabled"); 83 | }; 84 | ws.onerror = (_event) => { 85 | console.log("服务器连接失败!"); 86 | }; 87 | } else { 88 | // 浏览器不支持 WebSocket 89 | alert("您的浏览器不支持 WebSocket!"); 90 | } 91 | } 92 | 93 | let history = []; 94 | let history_index = -1; 95 | let current_command = ""; 96 | 97 | // 发送指令 98 | function sendCmd() { 99 | if (ws) { 100 | if (cmd.value) { 101 | history.push(cmd.value); 102 | if (history.length > 20) { 103 | history.shift(); 104 | } 105 | history_index = -1; 106 | } 107 | ws.send(cmd.value + "\n"); 108 | term.write(cmd.value + "\n\r"); 109 | cmd.value = ""; 110 | } else { 111 | console.log("服务器未连接!"); 112 | } 113 | } 114 | // 历史输入 115 | function getCmd1() { 116 | // If there is history, show last one 117 | if (history.length > 0) { 118 | // remember current command 119 | if (history_index === -1) { 120 | current_command = cmd.value; 121 | } 122 | if (history_index < history.length - 1) { 123 | history_index = history_index + 1; 124 | cmd.value = history[history.length - history_index - 1]; 125 | } 126 | } 127 | } 128 | function getCmd2() { 129 | if (history_index > -1) { 130 | history_index = history_index - 1; 131 | if (history_index >= 0) { 132 | cmd.value = history[history.length - history_index - 1]; 133 | } else { 134 | cmd.value = current_command; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /www/js/xterm-addon-attach.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Skipped minification because the original files appears to be already minified. 3 | * Original file: /npm/xterm-addon-attach@0.8.0/lib/xterm-addon-attach.js 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AttachAddon=t():e.AttachAddon=t()}(self,(function(){return(()=>{"use strict";var e={};return(()=>{var t=e;function s(e,t,s){return e.addEventListener(t,s),{dispose:()=>{s&&e.removeEventListener(t,s)}}}Object.defineProperty(t,"__esModule",{value:!0}),t.AttachAddon=void 0,t.AttachAddon=class{constructor(e,t){this._disposables=[],this._socket=e,this._socket.binaryType="arraybuffer",this._bidirectional=!(t&&!1===t.bidirectional)}activate(e){this._disposables.push(s(this._socket,"message",(t=>{const s=t.data;e.write("string"==typeof s?s:new Uint8Array(s))}))),this._bidirectional&&(this._disposables.push(e.onData((e=>this._sendData(e)))),this._disposables.push(e.onBinary((e=>this._sendBinary(e))))),this._disposables.push(s(this._socket,"close",(()=>this.dispose()))),this._disposables.push(s(this._socket,"error",(()=>this.dispose())))}dispose(){for(const e of this._disposables)e.dispose()}_sendData(e){this._checkOpenSocket()&&this._socket.send(e)}_sendBinary(e){if(!this._checkOpenSocket())return;const t=new Uint8Array(e.length);for(let s=0;s{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{constructor(){}activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})()})); 8 | //# sourceMappingURL=xterm-addon-fit.js.map -------------------------------------------------------------------------------- /www/js/xterm-addon-unicode14.js: -------------------------------------------------------------------------------- 1 | const UnicodeV14 = /** @class */ (function () { 2 | function UnicodeV14() { 3 | this.version = '14'; 4 | } 5 | 6 | UnicodeV14.prototype.wcwidth = function (num) { 7 | let x = widechar_wcwidth(num); 8 | if (x === widechar_widened_in_9) x = 2; 9 | if (x === widechar_private_use) x = 1; 10 | if (x === widechar_ambiguous) x = 1; 11 | if (x < 0) x = 0; 12 | return x; 13 | } 14 | return UnicodeV14; 15 | }()); 16 | 17 | const Unicode14Addon = /** @class */ (function () { 18 | function Unicode14Addon() { 19 | } 20 | 21 | Unicode14Addon.prototype.activate = function (terminal) { 22 | terminal.unicode.register(new UnicodeV14()); 23 | }; 24 | Unicode14Addon.prototype.dispose = function () { 25 | }; 26 | return Unicode14Addon; 27 | }()); 28 | -------------------------------------------------------------------------------- /www/js/xterm-addon-web-links.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Skipped minification because the original files appears to be already minified. 3 | * Original file: /npm/xterm-addon-web-links@0.8.0/lib/xterm-addon-web-links.js 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebLinksAddon=t():e.WebLinksAddon=t()}(self,(function(){return(()=>{"use strict";var e={6:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.LinkComputer=t.WebLinkProvider=void 0,t.WebLinkProvider=class{constructor(e,t,n,i={}){this._terminal=e,this._regex=t,this._handler=n,this._options=i}provideLinks(e,t){const i=n.computeLink(e,this._regex,this._terminal,this._handler);t(this._addCallbacks(i))}_addCallbacks(e){return e.map((e=>(e.leave=this._options.leave,e.hover=(t,n)=>{if(this._options.hover){const{range:i}=e;this._options.hover(t,n,i)}},e)))}};class n{static computeLink(e,t,i,r){const o=new RegExp(t.source,(t.flags||"")+"g"),[s,a]=n._getWindowedLineStrings(e-1,i),c=s.join("");let d;const l=[];for(;d=o.exec(c);){const e=d[0];try{const t=new URL(e),n=decodeURI(t.toString());if(e!==n&&e+"/"!==n)continue}catch(e){continue}const[t,o]=n._mapStrIdx(i,a,0,d.index),[s,c]=n._mapStrIdx(i,t,o,e.length);if(-1===t||-1===o||-1===s||-1===c)continue;const p={start:{x:o+1,y:t+1},end:{x:c,y:s+1}};l.push({range:p,text:e,activate:r})}return l}static _getWindowedLineStrings(e,t){let n,i=e,r=e,o=0,s="";const a=[];if(n=t.buffer.active.getLine(e)){const e=n.translateToString(!0);if(n.isWrapped&&" "!==e[0]){for(o=0;(n=t.buffer.active.getLine(--i))&&o<2048&&(s=n.translateToString(!0),o+=s.length,a.push(s),n.isWrapped&&-1===s.indexOf(" ")););a.reverse()}for(a.push(e),o=0;(n=t.buffer.active.getLine(++r))&&n.isWrapped&&o<2048&&(s=n.translateToString(!0),o+=s.length,a.push(s),-1===s.indexOf(" ")););}return[a,i]}static _mapStrIdx(e,t,n,i){const r=e.buffer.active,o=r.getNullCell();let s=n;for(;i;){const e=r.getLine(t);if(!e)return[-1,-1];for(let n=s;n{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.WebLinksAddon=void 0;const t=n(6),r=/https?:[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function o(e,t){const n=window.open();if(n){try{n.opener=null}catch(e){}n.location.href=t}else console.warn("Opening link blocked as opener could not be cleared")}e.WebLinksAddon=class{constructor(e=o,t={}){this._handler=e,this._options=t}activate(e){this._terminal=e;const n=this._options,i=n.urlRegex||r;this._linkProvider=this._terminal.registerLinkProvider(new t.WebLinkProvider(this._terminal,i,this._handler,n))}dispose(){var e;null===(e=this._linkProvider)||void 0===e||e.dispose()}}})(),i})()})); 8 | //# sourceMappingURL=xterm-addon-web-links.js.map --------------------------------------------------------------------------------