MCFPP——字符串体系
在MCFPP中,字符串分为两种,一种是string
,即我们通常意义上的字符串,另一种则是jstring
,即原始JSON文本。前者主要用于say命令,后者用途则广泛得多,比如tellraw
,title
等命令。MCFPP将这两种类型分开,让代码的操作更加清晰规范,同时也提供了转换方法,能将两者相护转换。
string
string表示一个字符串。要声明一个字符串,应该使用string
类型,例如string abc = "abc"
。
string
重写了+运算符,因此能够对字符串进行加运算。例如string ps = "abc" + "def"
,结果得到ps为”abcdef”。
和MCFPP中所有变量一样,string类型有编译时静态和动态两种方式。类似上文中的声明方式,编译器能发现自己能够跟踪到这个字符串的内容,因此在编译过程中会进行简单的替换。而动态则不同,动态字符串通常是由于将一个jstring
转换成string
类型而导致的。动态字符串储存在nbt中,以供操作。
得益于宏和data string
命令,让字符串的动态操作成为了可能。在1.19.4-的版本中,MCFPP只支持静态的字符串和原始JSON文本功能。
下面列出了string的一些API,以及实现的原理。实现原理的前提是,这个字符串是动态的。因为静态字符串根本不需要考虑很多的原理嘛。
inline string split(int startIndex, int endIndex)
切割一个字符串,对应原版的data string命令。返回一个字符串。
bool contains(string subString)
查询字符串中是否包含目标字符串。执行此方法时,首先获取subString的长度,然后对原字符串进行复制。首先查询字符串的0~subString.length是否为subString,然后查询1~subString.length+1,以此内推。这里我们在每次查询完毕后,直接将复制的字符串长度去掉最开头的字符,这样每次我们判断都只需要判断0~subString.length部分的字符串,从而提高优化。
inline int length()
返回字符串的长度,对应原版的data get命令
bool startsWith(string prefix)
bool endsWith(string suffix)
是否以指定字符串开头或结尾。原理类似contains方法。
char[] toCharArray()
将字符串转换为一个字符数组。原理是遍历字符串并将其储存在一个nbt数组中。
jstring toJString()
将这个字符串转换为jstring。
jstring
原始Json文本是Minecraft中最重要的文本展示方式。在展示实体,自定义名称,标题,聊天栏中,都会广泛地使用到原始JSON文本。原始JSON文本可以做到类似富文本的格式,还能显示记分板数字,NBT内容,甚至键位等。
在MCFPP中,所有的原始JSON文本都被默认为带有[],从而更好地进行加运算。声明jstring的方式可以为jstring j = "qwq"
,可以有隐式转换jstring j = 114514
。jstring重载了针对任意类型遍历的加操作。
动态的jstring被储存于nbt中。值得注意的是,储存状态下的jstring不带有[],这是为了更方便地进行加操作。同时,默认会携带有一个,
作为结尾,这也是便于加操作。在调用jstring
变量时,会自动在命令中加上[]以及在末尾加一个””作为终止符。即在命令中,会用类似tellraw @s [$(j)""]
这样的方式调用。
动态的jstring的储存分为两个部分。第一个部分是调用在命令中时使用的,也就是传入宏参数的部分,是通常意义上的原始JSON文本。第二部分是以NBT形式储存的,表示jstring中的成员。例如jstring j = "the value is " + value
中,jstring的NBT储存格式为:
j:{ str:"\"the value is\", {\"score\" :{\"object\": \"test\", \"name\": \"value\"}}", data: [ { type: "string", value: "the value is" }, { type: "int", value: { name: "value" } } ] }
为了更清晰,上述我们使用了换行来展示NBT的内容。
当使用加法新增内容时,会在str后加长字符串,同时在data中添加和新内容相关的内容。注意,如果新的内容是jstring,则会合并data列表。
jstring展示的文本内容是动态的。例如上文中,如果修改了value
的值,那么使用print
方法打印出的文本也是不同的。如果要保留静态的内容,可以使用toString
方法获取它的string文本。转换为string后的jstring将失去成员数据的内容,即使稍后将其重新转换为jstring也是如此。
下面列出了jstring的一些api。同样的,这些api的实现原理是针对动态情况下提出的,也只支持1.19.4以上的版本。
string toString()
将这个jstring转换为string。通过宏完成。
jstring insert(int index, object o)
插入一个元素。需要对jstring的str进行重新计算。
jstring remove(int index)
移除一个元素。需要对jstring的str进行重新计算。
bool contains(object o)
是否包含某个元素。
static jstring getFromList(List list)
从列表中获取一个jstring。jstring本身便有一个data的list作为成员,因此从list中获取jstring成为了一件很自然的事情。这个方法会自动检查list中的每个元素是不是标准的mcfpp变量储存形式,以便jstring拥有可变性。