Releases: HimxhMC/HimDSL
Release list
HimDSL v4.0
新增功能:
1 自由监听
监听Bukkit原生事件 举例 @EventHandler void doSome(event(AsyncPlayerChatEvent)) {}
监听任意插件 事件 举例 @EventHandler void doSome2(event("完整的类路径")) {}
-这会尝试直接用Class forName来加载它。
2多范式
现在数据结构函数可以支持双范式和混合使用。
int main(){
var st = stack();
st.push(10).push(20);
var top = st.pop();
var empty = st.isEmpty();
var q = queue();
q.offer(1).offer(2);
var val = q.poll();
var m = map();
m.put("key1", 100).put("key2", 200);
var value = m.get("key1");
var v = vector();
v.add(5).add(6);
var first = v.get(0);
var size = v.size();
var ss = set();
ss.add(1).add(2);
var has = ss.contains(1);
var str = "Hello";
var upper = str.toUpperCase();
var replaced = str.replace("l", "x");
runcmd("CONSOLE","say "+top+" "+empty+" "+val+" "+value+" "+first+" "+size+" "+has+" "+upper+" "+replaced);
}
3字符串操作
为了让C++开发者舒服,允许直接修改,
底层是String和char[]互转。
struct Person {
string name;
};
int main(){
var str = "Hello";
str[0] = 'h'; // 变为 "hello"
str[4] = 33; // 变为 "hell!"
Person p;
p.name = "Alice";
p.name[0] = 'X'; // 变为 "Xlice"
runcmd("CONSOLE","say "+str+" "+p.name);
}
4文件操作
可以打开,读全部,读某一行,写入,删除,寻找是否存在
int main(){
var handle = fopen("test.txt", "w");
fwrite(handle, "Hello, World!\n");
fwrite(handle, "第二行");
fclose(handle);
var h2 = fopen("test.txt", "r");
var content = fread(h2);
runcmd("CONSOLE","say "+content);
fclose(h2);
var lines = freadlines("data.txt");
fwritelines("output.txt", lines);
if (fexists("config.json")) {
fdelete("config.json");
}
}
** 性能测试 **
在纯递归无缓存的情况下计算fib(25)耗时:
0.6s-0.8s
压栈可达300层左右。
HimDSL v3.1
main函数支持传参
参数在使用/himdsl run <文件> 后挨个写。
int main(int num){
bool result = isPrime(num);
runcmd("CONSOLE","say "+result);
}
bool isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return true;
// 快速排除 2 和 3 的倍数
if (n % 2 == 0 || n % 3 == 0) return false;
// 只检查 6k-1 和 6k+1 的数
// i 从 5 开始,每次增加 6
for (var i = 5; i * i <= n; i = i + 6) {
// 检查 i (即 6k-1) 和 i+2 (即 6k+1)
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
输入/himdsl run 新质数判断.dsl 17 来执行
修复了玩家占位符不支持结构体的问题
修复了玩家最后操作的方块和命令由于实例引用错误导致无法读值的陈年老bug
HimDSL v3.0
结构体上线!
变更:
选择器返回的是内置结构体Entity的实例
多个选中会返回一个Entity[]。
@e选择器支持,但是需要加载区块。
int main() {
Entity players = @A; //是a 不是A Github问题
var first = players.get(0);
runcmd("CONSOLE", "say First player: " + first.name + " at " + first.x + ", " + first.y + ", " + first.z);
}
int main() {
var entities = @e[limit=10]; //=Entity entities 同理那个是e不是E
for (var i = 0; i < entities.size(); i = i + 1) {
var ent = entities.get(i);
runcmd("CONSOLE", "say Entity: " + ent.type + " at " + ent.x + ", " + ent.y + ", " + ent.z);
}
}
struct Student {
string name;
int id;
double math;
double english;
double chinese;
};
int main() {
var students = vector(); // 必须初始化
Student s1;
s1.name = "张三";
s1.id = 1001;
s1.math = 88.5;
s1.english = 92.0;
s1.chinese = 76.5;
students.add(s1);
Student s2;
s2.name = "李四";
s2.id = 1002;
s2.math = 95.0;
s2.english = 89.5;
s2.chinese = 93.0;
students.add(s2);
Student s3;
s3.name = "王五";
s3.id = 1003;
s3.math = 72.0;
s3.english = 68.0;
s3.chinese = 81.0;
students.add(s3);
var total = 0.0;
var count = students.size();
for (var i = 0; i < count; i = i + 1) {
var stu = students.get(i);
var sum = stu.math + stu.english + stu.chinese;
var avg = sum / 3.0;
total = total + sum;
runcmd("CONSOLE", "say 学生 " + stu.name + " (ID:" + stu.id + ") 总分: " + sum + " 平均分: " + avg);
}
var avgTotal = total / count;
runcmd("CONSOLE", "say 全班总平均分: " + avgTotal);
}
HimDSL v2.4
添加了大数字加减乘除,vector和set的支持。
int main() {
//1. 创建 vector 并操作
var v = vector();
v.add(10);
v.add(20);
v.add("hello");
var size = v.size();
var first = v.get(0);
var containsHello = v.contains("hello");
v.remove(1);
var afterRemove = v.size();
//2. 创建 set 并操作
var ss = set();
ss.add("apple");
ss.add("banana");
ss.add("apple"); // 重复元素,不会增加
var setSize = ss.size();
var containsApple = ss.contains("apple");
//3. 通过 runcmd 输出结果到控制台(使用 say 命令)
runcmd("CONSOLE", "say [Vector] size = " + size);
runcmd("CONSOLE", "say [Vector] first = " + first);
runcmd("CONSOLE", "say [Vector] contains 'hello'? " + containsHello);
runcmd("CONSOLE", "say [Vector] size after remove index 1 = " + afterRemove);
runcmd("CONSOLE", "say [Set] size = " + setSize);
runcmd("CONSOLE", "say [Set] contains 'apple'? " + containsApple);
}
void main() {
var a = "12345678901234567890.12345";
var b = "98765432109876543210.98765";
// 加法
var sum = bigAdd(a, b);
runcmd("CONSOLE","say sum = " + sum);
// 减法
var diff = bigSub(a, b);
runcmd("CONSOLE","say diff = " + diff);
// 乘法
var prod = bigMul(a, b);
runcmd("CONSOLE","say prod = " + prod);
// 除法(保留 10 位小数)
var quot = bigDiv(a, b, 10);
runcmd("CONSOLE","say quot = " + quot);
// 精确除法(必须整除)
var exact = bigDivExact("10", "2");
runcmd("CONSOLE","say exact = " + exact); // 输出 "5"
}
HimDSL 2.3
HimDSL v2.2
初步实现和HimDungeons的互相接入。
增添了亿些数学函数。
VS Code代码高亮配置可在仓库内下载,提供windows系统操作方式。
HimDSL 2.1
现在所有的监听器任务和异步任务
都需明确使用
start("函数名"); stop("函数名");来启动或者关闭。
使用himdsl debug off/on可以关闭复杂的调试日志。
PS:一个文件只start了任务没有stop又不想重启服务器?
脚本里start改成stop,再次运行。
示例脚本。
/*
- HimDSL 事件监听教程脚本
- 功能:玩家可通过 /listen <事件名> 开启监听,/unlisten <事件名> 关闭监听。
- 支持的事件:chat, join, quit, move, break, place, command
- 默认所有监听器均为关闭状态,需手动开启。
*/
int main(){
// 启动命令监听器,以便玩家能够使用 /listen /unlisten 控制其他监听器
start("onCommand");
// 发送帮助信息
runcmd("CONSOLE","say === HimDSL 事件控制教程 ===");
runcmd("CONSOLE","say /listen <事件名> - 开启事件监听");
runcmd("CONSOLE","say /unlisten <事件名> - 关闭事件监听");
runcmd("CONSOLE","say 可用事件: chat, join, quit, move, break, place, command");
runcmd("CONSOLE","say 例如: /listen chat");
}
// ---------- 命令处理监听器 ----------
// 监听玩家发送的命令,解析并控制其他监听器的启停
@eventhandler void onCommand(event(PlayerCommandPreprocessEvent)) {
player p = @s;
var msg = event.getMessage(); // 获取完整命令,如 "/listen chat"
// 处理 /listen 命令
if(startsWith(msg, "/listen")) {
var parts = split(msg, " "); // 按空格分割
if(length(parts) < 2) {
runcmd("CONSOLE","say " + $player(p,name)$ + " 用法: /listen <事件名>");
event.setCancelled(true); // 阻止原命令执行(避免冲突)
return;
}
var name = parts[1]; // 获取事件名
// 根据事件名启动对应的监听器
if(name == "chat") {
start("onChat");
runcmd("CONSOLE","say 已开启聊天监听(消息将自动转为小写)");
} else if(name == "join") {
start("onJoin");
runcmd("CONSOLE","say 已开启玩家加入监听(会显示自定义欢迎消息)");
} else if(name == "quit") {
start("onQuit");
runcmd("CONSOLE","say 已开启玩家退出监听(会显示自定义告别消息)");
} else if(name == "move") {
start("onMove");
runcmd("CONSOLE","say 已开启玩家移动监听(会记录移动信息到日志)");
} else if(name == "break") {
start("onBreak");
runcmd("CONSOLE","say 已开启方块破坏监听(会记录破坏信息到日志)");
} else if(name == "place") {
start("onPlace");
runcmd("CONSOLE","say 已开启方块放置监听(会记录放置信息到日志)");
} else if(name == "command") {
// 注意:命令监听器本身也可开关,但若关闭则无法再通过命令控制,建议保持开启
runcmd("CONSOLE","say 命令监听器不建议关闭,否则无法使用 /listen 和 /unlisten");
} else {
runcmd("CONSOLE","say 未知事件: " + name + ",可用: chat, join, quit, move, break, place, command");
}
event.setCancelled(true); // 阻止原命令
return;
}
// 处理 /unlisten 命令
if(startsWith(msg, "/unlisten")) {
var parts = split(msg, " ");
if(length(parts) < 2) {
runcmd("CONSOLE","say " + $player(p,name)$ + " 用法: /unlisten <事件名>");
event.setCancelled(true);
return;
}
var name = parts[1];
if(name == "chat") {
stop("onChat");
runcmd("CONSOLE","say 已关闭聊天监听");
} else if(name == "join") {
stop("onJoin");
runcmd("CONSOLE","say 已关闭玩家加入监听");
} else if(name == "quit") {
stop("onQuit");
runcmd("CONSOLE","say 已关闭玩家退出监听");
} else if(name == "move") {
stop("onMove");
runcmd("CONSOLE","say 已关闭玩家移动监听");
} else if(name == "break") {
stop("onBreak");
runcmd("CONSOLE","say 已关闭方块破坏监听");
} else if(name == "place") {
stop("onPlace");
runcmd("CONSOLE","say 已关闭方块放置监听");
} else if(name == "command") {
runcmd("CONSOLE","say 命令监听器不建议关闭,否则无法使用 /listen 和 /unlisten");
} else {
runcmd("CONSOLE","say 未知事件: " + name + ",可用: chat, join, quit, move, break, place, command");
}
event.setCancelled(true);
return;
}
// 其他命令不做处理,允许正常执行
}
// ---------- 聊天事件监听 ----------
// 功能:将玩家发送的消息自动转为小写(并默认屏蔽敏感词,可自行扩展)
@eventhandler void onChat(event(AsyncPlayerChatEvent)) {
player p = @s;
var msg = event.getMessage();
// 简单示例:将消息转为小写
var newMsg = toLowerCase(msg);
event.setMessage(newMsg);
// 可扩展屏蔽敏感词(示例)
if(contains(msg, "fuck") || contains(msg, "shit")) {
event.setCancelled(true);
runcmd("CONSOLE","say " +
}
}
// ---------- 玩家加入事件 ----------
@eventhandler void onJoin(event(PlayerJoinEvent)) {
player p = @s;
var name =
// 自定义加入消息
event.setJoinMessage("§a欢迎 " + name + " 进入服务器!");
// 还可执行其他操作,如赠送初始物品等
}
// ---------- 玩家退出事件 ----------
@eventhandler void onQuit(event(PlayerQuitEvent)) {
player p = @s;
var name =
event.setQuitMessage("§c" + name + " 离开了服务器,再见!");
}
// ---------- 玩家移动事件 ----------
@eventhandler void onMove(event(PlayerMoveEvent)) {
player p = @s;
var from = event.getFrom();
var to = event.getTo();
// 仅当坐标有明显变化时输出日志(避免刷屏)
if(from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ()) {
var name =
runcmd("CONSOLE","say " + name + " 移动到 (" + to.getX() + ", " + to.getY() + ", " + to.getZ() + ")");
}
}
// ---------- 方块破坏事件 ----------
@eventhandler void onBreak(event(BlockBreakEvent)) {
player p = @s;
var block = event.getBlock();
var blockType = block.getType().name().toLowerCase();
var name =
runcmd("CONSOLE","say " + name + " 破坏了 " + blockType + " 在 (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")");
}
// ---------- 方块放置事件 ----------
@eventhandler void onPlace(event(BlockPlaceEvent)) {
player p = @s;
var block = event.getBlock();
var blockType = block.getType().name().toLowerCase();
var name =
runcmd("CONSOLE","say " + name + " 放置了 " + blockType + " 在 (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")");
}
HimDSL 2.0
更新了事件监听器。可以查找当前Bukkit系列服务器的事件
也支持event.setCancelled(true); event.getPlayer();等原生操作。
更新了目标选择器@s ,仅在监听器函数中起效,表明触发事件的此玩家。
这里是 @后面加上EventHandler,不是全小写!
@eventhandler void onChat(event(AsyncPlayerChatEvent)) {
player p = @s;
var msg = event.getMessage();
// 屏蔽敏感词
if(contains(msg, "fuck") || contains(msg, "shit")) {
event.setCancelled(true);
var saysome="say "+$player(p,name)$+"使用了不文明语言,已拦截";
runcmd("CONSOLE",saysome);
}
// 自动将聊天转为小写
var newMsg = toLowerCase(msg);
event.setMessage(newMsg);
}
int main(){}
下面的几位是@注解的事情,本项目只有我单人开发。
HimDSL 1.1
玩家占位符修复+重构了一些内容,rand(double,double)已经支持。
注意玩家占位符如果要输入参数请先toInt(参数),不然可能会报字符串异常。
使用say服务器命令等进行输出的时候,不要在字符串输出任何的括号,不然会出解析问题
HimDSL 1.0
HimDSL v1.0底层修复与新功能
版本简介
本次为虚拟机底层关键性更新,集中修复字符串缺陷、函数调用栈、新增内置容器(栈、队列、Map字典),补齐基础语言能力。
本次更新是开发占位符解析、复杂递归算法、批量数据处理脚本的核心基础版本。
✨新增功能
内置容器库
@BukkitRunnable注解 不需要在main()里调用函数,会自己执行。
@Deprecated注解
支持注册定时任务。
提供了一部分占位符支持。大部分支持+将会支持的占位符:
占位符列表:占位符
player系占位符
引用方式;$player(<玩家变量名>,<属性>)$ 或者$p(<玩家变量名>,<属性>)$
属性:
Int x 获取玩家的X坐标。
Int y 获取玩家的Y坐标。
Int z 获取玩家的Z坐标。
Double yaw 获取玩家的视角。
Double pitch 获取玩家的视角。
Double hp 获取玩家生命值。
Double hungry 获取玩家的饱食度。
Bool openGui 玩家是否打开GUI页面(包括工具方块提供的GUI和其他命令调出的GUI)
Bool handleJoin 玩家加入
Bool handleLeave 玩家离开
String breakType 最后一次破坏的方块类型
Int[3] breakPos 最后一次的破坏位置
String buildType 最后一次放置的方块类型
Int[3] buildPos 最后一次的放置位置
String runCommnad 最后一次使用的命令
String name 玩家名
String uuid 玩家的UUID
String slot[某一个ID] 玩家物品栏
String mainhand 主手物品
String offhand 副手物品
Bool isSneaking:玩家是否潜行,很多跑酷和躲猫猫需要
Bool isSprinting:玩家是否疾跑
String gamemode:玩家游戏模式,用于权限判断
Int expLevel:经验等级,RPG 小游戏常用
String world:玩家所在世界名,多世界小游戏必备
引用方式:$boss(<属性>)$或者$b(属性)$
属性包括 x,y,z,yaw,pitch,world
rand类占位符
引用方式:直接调用。
rand() 同C++里面的那个rand()举例:var a=rand();
int rand(int,int) 在范围内选一个整数
double rand(double,double) 在范围内选一个浮点数
double randChoose(number,number,number……) 随机选一个返回
world类占位符
引用方式:$world(<属性>)$ 或者$w(<属性>)$
属性:
String name 世界名
String block[][][] 某个位置的方块类型(Material 枚举名)
Bool isContainer[][][] 某个位置的方块是否是容器
String contain[x][y][z][slot] 某个位置的容器的某一格的内容。
Bool hasPlayer(String世界名) 某个世界有无玩家
server类占位符
引用方式:$server(<属性>)$或者$s(<属性>)$
属性:
Double tps 服务器当前tps
Double mspt 服务器当前的mspt
Double ping(String) 某个玩家的延迟
Bool ServerLoadEvent
Bool ServerCloseEvent
Bool onPluginEnable
Bool onPluginDisable
引用方式:直接使用
runcmd(<执行者>,<String原版命令>);
执行者可以是 “CONSOLE”,或者 “$player(<玩家变量名>,name)$”
命令可以是服务器支持的任何命令。
变量:只提供$haveVar(<变量名>)$检测有没有该变量存在。
示例脚本1:玩家占位符
`int main(){
player p = @p[limit=1];
// 玩家信息
runcmd("CONSOLE","say 玩家: " + $player(p,name)$);
runcmd("CONSOLE","say 坐标: " + $player(p,x)$ + ", " + $player(p,y)$ + ", " + $player(p,z)$);
runcmd("CONSOLE","say 血量: " + $player(p,hp)$);
runcmd("CONSOLE","say 饥饿度: " + $player(p,hungry)$);
// 世界信息
var worldName = $world(name)$;
runcmd("CONSOLE","say 当前世界: " + worldName);
runcmd("CONSOLE","say 方块类型(0,64,0): " + $world(block, 0, 64, 0)$);
// 服务器信息
runcmd("CONSOLE","say 当前TPS: " + $server(tps)$);
runcmd("CONSOLE","say MSPT: " + $server(mspt)$);
}示例脚本2:随机数int main(){
int a=rand();
int b=rand(10,1000);
double c = 20.0 + rand() * (57.3 - 20.0);
runcmd("CONSOLE","say a,b,c="+a+" "+b+" "+c);
}示例脚本3:玩家加入监听器int main(){
runcmd("CONSOLE","say 启动玩家在线检测,每2秒检查一次");
// main 立即结束,定时任务接管
}
@BukkitRunnable void report() sche=2s{
if($world(hasPlayer, $world(name)$)$){
runcmd("CONSOLE","say 当前有玩家在线");
} else {
runcmd("CONSOLE","say 当前无玩家在线");
}
}`
注意:由于注解会使用@,下面的贡献者都不要相信,本项目只有本人单独开发。