你是否想要给自己的地图添加一个有逼格而又硬核的结尾?

那就试试这个数据包!

简单的字幕是一个如此简单的数据包,以至于不同版本之间命令的隔阂也不能让它失去作用。换句话说,它在1.14到1.18的版本,乃至未来的版本都可能通用!

简单字幕允许使用者创建、播放一个电影结尾般的滚动字幕,而不用改变终末之诗,就像下面一样。

注:背景需要自己设置

这个数据包的原理就是利用命名盔甲架不断上升的方式,以每个盔甲架展示每一行字幕,盔甲架上升就是字幕的滚动。

由于这次是一个前置数据包,因此没有过多的操作页面。下面将详细说明这个数据包的使用方法。别担心!很简单的!

字幕文件的格式

要想生成一个字幕,首先需要定义一个字幕文件(不然你的字幕要怎么显示出来啊)。字幕文件应当被统一储存在<存档名>\datapacks\Subtitle\data\subtitle\functions\txt文件夹下,这样程序才能读取出来。每一个字幕文件都是一个.txt文本文档,而这个文件的名字则是将会生成的字幕的文字。字幕文件的编辑格式非常简单,下面就是一个样本。这个样本也被包含在了数据包中。

datapacks\Subtitle\data\subtitle\functions\txt\example.txt

#/#/本文件储存字幕的内容,程序将逐行读取该文件的内容
#/#/以#/#/开头的一行不会被转为字幕函数,也就是注释
#/#/文件的名字即为字幕的名字,所有函数都将自动生成并写入
#/#/值得注意的是,所有的字幕默认中间对齐
#/#/以####开头的一行定义了下一行文字的颜色等属性,错误的属性将被忽略。不同属性间用|分割,属性不分先后
------------------------
####gold
简单的字幕
####gold
Simple Subtitle

####bold
制作
Alumopper

####bold
发布于
mcbbs
BiliBili

####bold|green
mcbbs ID
Alumopper

####bold|aqua
BiliBili
Alumopper

####bold
-感谢使用-

文件中的属性也就是指原始JSON文本中的斜体、粗体、删除线、下划线、混乱属性。颜色属性就是16中颜色。详细查看wiki:原始JSON文本格式 – Minecraft Wiki_BWIKI_哔哩哔哩 (biligame.com)

生成程序的使用

在\datapacks\Subtitle\data\subtitle\functions\文件夹下(也就是和命令函数一个文件夹)有一个叫做Subtitle.exe的程序,这个程序承担了读取字幕文件生成字幕的工作。你可以直接双击打开这个程序,然后输入这个字幕文件的文件名。注意,不用加上文件的.txt拓展名。如果成功解析了字幕文件,就会生成一堆字幕函数。如果找不到字幕文件或者字幕文件中有错误,那么程序发出错误或者警告。

当然,程序中有一些简单的命令,分别是:

<字幕文件名>     生成字幕
*exit                   退出
*help                  帮助(展示所有程序内部命令)
*list                    展示所有可用字幕文件
*set                    设置

程序运行截图。图中程序已经执行过了*help

关于设置,目前只有一个设置可以改变,就是interval 即行间距。默认是30(也就是每隔30tick生成一个盔甲架)。使用方法输入*set查看。

游戏中调用字幕

如果你成功地生成了一段字幕,那么展示字幕用的函数将会包含在..(路径省略)/functions/subtitles/<字幕名>/文件夹下,一共包含start、timer、end三个函数。调用start函数会让调用者进入观看字幕的状态,也就是说,一人一字幕,同时也要注意在调用时指明观看字幕的实体。timer就是生成字幕用的。end将会停止播放字幕。字幕播放完毕会自动调用end函数,你也可以手动调用打断字幕的播放。         
例如,执行/function subtitle:subtitles/example/start就能显示example字幕。
在播放字幕时,玩家会被锁定视角以及位置。

下载

最后更新于:2021.8.5

b站使用介绍以及演示视频戳这里~:
教你在mc中做出电影般的结尾!地图瞬间高级了!

源码

Program.cs

using System;
using System.Collections;
using System.IO;
using System.Text;

namespace Subtitle
{
    class Program
    {
        static int interval = 10;

        static void Main(string[] args)
        {
            Console.WriteLine("字幕生成器 by Alumopper");
            Console.WriteLine("注意,请将字幕文件放到functions下的txt文件夹中,将本程序直接放到functions文件夹下,否则会读取失败");
            bool b = true;
            while (b)
            {
                Console.Write(">>>");
                string s = Console.ReadLine();
                //命令使用
                if (s.StartsWith("*"))
                {
                    if (s.StartsWith("*set"))
                    {
                        s = s.Substring(4);
                        string[] arg = s.Split(' ');
                        if (arg.Length == 1)
                        {
                            //设置帮助
                            Console.ForegroundColor = ConsoleColor.Blue;
                            Console.WriteLine("用法:*set <设置项> [参数]");
                            Console.WriteLine("可用的<设置项>有:\ninterval\t\t行间距");
                            Console.WriteLine("参数若不设置,则为默认值");
                            Console.ResetColor();
                        }
                        else if (arg.Length == 3)
                        {
                            //读取参数
                            switch (arg[1])
                            {
                                case "interval":
                                    {
                                        try
                                        {
                                            interval = int.Parse(arg[2]);
                                            Console.ForegroundColor = ConsoleColor.Blue;
                                            Console.WriteLine("已将设置interval设置为{0}", interval);
                                            Console.ResetColor();
                                        }
                                        catch (Exception e)
                                        {
                                            Console.ForegroundColor = ConsoleColor.Red;
                                            Console.WriteLine("[错误]" + e.Message);
                                            Console.ResetColor();
                                        }
                                        break;
                                    }
                                default:
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        Console.WriteLine("[错误]未知的设置项" + arg[1]);
                                        Console.ResetColor();
                                        break;
                                    }
                            }

                        }
                    }
                    else
                    {
                        switch (s)
                        {
                            case "*exit":
                                {
                                    //退出
                                    b = false;
                                    break;
                                }
                            case "*help":
                                {
                                    //帮助
                                    Console.ForegroundColor = ConsoleColor.Blue;
                                    Console.WriteLine("<字幕文件名>\t\t生成字幕");
                                    Console.WriteLine("*exit\t\t\t退出");
                                    Console.WriteLine("*help\t\t\t帮助");
                                    Console.WriteLine("*list\t\t\t展示所有可用字幕文件");
                                    Console.WriteLine("*set\t\t\t设置");
                                    Console.ResetColor();
                                    break;
                                }
                            case "*list":
                                {
                                    //列出可用文件
                                    Console.ForegroundColor = ConsoleColor.Blue;
                                    Console.WriteLine("目前可用文件");
                                    string[] files = Directory.GetFiles("txt", "*.txt");
                                    foreach (string file in files)
                                    {
                                        Console.WriteLine(file);
                                    }
                                    Console.ResetColor();
                                    break;
                                }
                            default:
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    Console.WriteLine("[错误]未知的命令" + s);
                                    Console.ResetColor();
                                    break;
                                }
                        }
                    }
                    continue;
                }
                Console.WriteLine("正在尝试读取" + s + ".txt");
                try
                {
                    string[] ss = File.ReadAllLines("txt\\" + s + ".txt");
                    Directory.CreateDirectory("subtitles\\" + s);
                    File.Create("subtitles\\" + s + "\\timer.mcfunction").Close();
                    File.Create("subtitles\\" + s + "\\start.mcfunction").Close();
                    File.Create("subtitles\\" + s + "\\end.mcfunction").Close();
                    //写入timer.mcfunction
                    ReadAndWrite(ss, s);
                    //写入start.mcfunction
                    WriteStart(s);
                    //写入tick.mcfunction
                    WriteTick(s);
                    //写入end.mcfunction
                    WriteEnd(s);
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("字幕{0}生成完毕!", s);
                    Console.ResetColor();
                }
                catch (Exception e)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("[错误]" + e.Message);
                    Console.ResetColor();
                }
            }
        }

        static void WriteEnd(string s)
        {
            //tag @a remove subt_example_tag
            //tag @a remove subt_watching
            //scoreboard players set subt_example subt_timer -1
            //kill @e[tag = subt_line, type = armor_stand]
            File.WriteAllLines("subtitles\\" + s + "\\end.mcfunction", new string[] { "tag @a remove subt_" + s + "_tag", "tag @a remove subt_watching", "scoreboard players set subt_" + s + " subt_timer -1", "kill @e[tag=subt_line, type=armor_stand]" });
        }

        static void WriteTick(string s)
        {
            //execute if score subt_example subt_timer matches 0.. run scoreboard players add subt_example subt_timer 1
            //execute as @a[tag = subt_example_tag] at @s run function subtitle: subtitles / example / timer
            File.AppendAllLines("subtitles\\tick.mcfunction", new string[] { "execute as @a[tag=subt_" + s + "_tag] at @s run function subtitle:subtitles/" + s + "/timer", "execute if score subt_" + s + " subt_timer matches 0.. run scoreboard players add subt_" + s + " subt_timer 1" });
        }

        static void WriteStart(string s)
        {
            //tag @s add subt_example_tag
            //scoreboard players set subt_example subt_timer 0
            File.AppendAllLines("subtitles\\" + s + "\\start.mcfunction", new string[] { "tag @s add subt_watching" });
            File.AppendAllLines("subtitles\\" + s + "\\start.mcfunction", new string[] { "tag @s add subt_" + s + "_tag" });
            File.AppendAllLines("subtitles\\" + s + "\\start.mcfunction", new string[] { "scoreboard players set subt_" + s + " subt_timer 0" });
        }

        static void ReadAndWrite(string[] ss, string name)
        {
            //储存文本属性
            Text t = new Text();
            //tick数
            int timer = 0;
            for (int i = 0; i < ss.Length; i++)
            {
                //分析每一行文字
                if (ss[i].StartsWith("#/#/"))
                {
                    //为注释,忽略
                    continue;
                }
                else if (ss[i].StartsWith("####"))
                {
                    //声明了属性,进行分割
                    string a = ss[i].Substring(4);
                    string[] b = a.Split('|');
                    t.Set(b, i);
                }
                else
                {
                    //为字幕文本,进行输出
                    //execute if score subt_example subt_timer matches 10 run summon armor_stand ~1 ~-5 ~ {Invisible:true,CustomNameVisible:true,Tags:["subt_line"],NoGravity:1b,CustomName:'{"text
                    string output = ("execute if score subt_" + name + " subt_timer matches " + timer + " run summon armor_stand ~2 ~-5 ~ {Invisible:true,CustomNameVisible:true,Tags:[\"subt_line\"],NoGravity:1b,CustomName:'{\"text\":\"" + ss[i] + "\"");
                    // + "}'}"
                    if (t.Color != null)
                    {
                        //如果有颜色
                        output += (",\"color\":\"" + t.Color + "\"");
                    }
                    if (t.Other.Count != 0)
                    {
                        //如果有属性
                        foreach (string s in t.Other)
                        {
                            output += (",\"" + s + "\":true");
                        }
                    }
                    output += "}'}\n";
                    //Console.WriteLine(output);
                    using (FileStream f = new FileStream("subtitles\\" + name + "\\timer.mcfunction", FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
                    {
                        byte[] buffer = Encoding.UTF8.GetBytes(output);
                        f.Write(buffer, 0, buffer.Length);
                    }
                    timer += interval;
                    t = new Text();
                }
            }
            File.AppendAllLines("subtitles\\" + name + "\\timer.mcfunction", new string[] { "execute if score subt_" + name + " subt_timer matches " + (timer + 120) + " run function subtitle:subtitles/" + name + "/end" });
        }
    }
}

Text.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Subtitle
{
    public class Text{
        private string _color;
        public string Color
        {
            get { return this._color;}
        }

        private ArrayList _other = new ArrayList();
        public ArrayList Other
        {
            get { return this._other; }
        }

        public static ArrayList colors = new ArrayList();
        public static ArrayList others = new ArrayList();

        public Text()
        {
            colors.Add("black");
            colors.Add("dark_blue");
            colors.Add("dark_green");
            colors.Add("dark_aqua");
            colors.Add("dark_red");
            colors.Add("dark_purple");
            colors.Add("gold");
            colors.Add("gray");
            colors.Add("dark_gray");
            colors.Add("blue");
            colors.Add("green");
            colors.Add("aqua");
            colors.Add("red");
            colors.Add("light_purple");
            colors.Add("yellow");
            colors.Add("white");

            others.Add("bold");
            others.Add("italic");
            others.Add("underlined");
            others.Add("strikethrough");
            others.Add("obfuscated");
        }

        public static bool IsColor(string s)
        {
            return colors.Contains(s);
        }

        public static bool IsOther(string s)
        {
            return others.Contains(s);
        }

        public void Set(string[] ss,int i)
        {
            //分析属性
            foreach(string s in ss)
            {
                if (IsColor(s))
                {
                    if (_color != null)
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("[警告]在{0}行出现过多的颜色属性", i - 1);
                        Console.ResetColor();
                    }
                    _color = s;
                }
                else if (IsOther(s))
                {
                    _other.Add(s);
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("[警告]在{0}行出现无效的属性", i - 1);
                    Console.ResetColor();

                }
            }
        }
    }
}

发表回复