= 创作分享 =
编程开发
[CT]开发日志
墨言魂靈

[CT]开发日志

墨言魂靈 于 2023-5-24 14:31 ( 11月前 ) [复制链接] [只看楼主] [打印]
3020 82
墨言魂靈
目前打算将CT拆成多个小模块进行开发,到最后合并成一个(所以Washable之类的拆分出去是正常的)。
以及...由于种种问题,CT放弃了更加快速的内置渲染(主要是技术问题)。
所以CT的文件大小可能会被data占掉一大半...(事实上这也是完全没有办法的办法...除了原GT好像还真没人敢用...)
城市喧闹,森林归宿。
终有一天,钢筋的海洋会在硝烟中化为尘土。
而那些阴影下的朝阳后裔,将重新统治这个世界
罪恶的本源出自于何?无非是过度的生气
发表于 2023-6-3 08:09:31 | 只看该作者

回复 | 举报

墨言魂靈
由于总所周知的Forge注册难问题,所以CT打算重新制作一个基于nbt的“数据值”系统。
这样不仅可以节约注册表空间,还可以省去一堆不必要的麻烦(需要注册好几个方块实体类型)。
(也就是说会出现/give @s crafttech:material.item 1 {MaterialSet:"golden", MaterialPart:"plate"}这种在高版本看起十分魔幻的东西)

【毕竟开发的第一铁律是能够运行,效率都是是后话了】
城市喧闹,森林归宿。
终有一天,钢筋的海洋会在硝烟中化为尘土。
而那些阴影下的朝阳后裔,将重新统治这个世界
罪恶的本源出自于何?无非是过度的生气
发表于 2023-6-5 23:48:30 | 只看该作者

回复 | 举报

墨言魂靈
CT的材质集主要是按照GT的思路来写的(思路相同但实现不同),目前有如下字段:

MaterialForm即一个材质集中“物品”形式的对应形式(比如说:红宝石的物品形式单质是红宝石【宝石】、铁的物品形式单质是铁锭【固体锭】)

因为CT现在用了“元数据”……所以物品与物品的区别方式是nbt。
所以尝试获取一个不带nbt的材质部件是不安全的。

至于“元数据”的实现逻辑——
首先,需要数据区分的物品/方块必须要带有nbt(当然,你要乐意覆写原版的metaNbt读写也行,但CT不打算做此类危险操作),
CT中材质部件的两个“元数据”的标签是"MaterialSet"和"MaterialPart"(用于标记这个物品/方块是哪种材质的哪种部件)。

使用“元数据”还有以下几个好处:

只需要注册一些对应纹理的模型,然后用使用一个类(这不比挨个注册物品/方块模型好实现多了)进行渲染(只要我找到了渲染单个模型的方法)即可
理论上可能更节省运行内存(需要要加载的类的数量少了)
很多东西都可以直接写代码里(不用去为每一个物品/方块安排对应的模型)

坏处:

无法模块化(只能把全部的逻辑都堆在一个物品/方块上)
更加消耗运算资源(多了数道判断和获取数据的tick)
兼容性差(除非主动去兼容,否则与其他Mod的同类物品判断方法不通用【因为高版本其他Mod的物品判断实现大多都不考虑其是否附加数据】)
过时、被移除的接口(必须重新造轮子【虽然并不难】)
城市喧闹,森林归宿。
终有一天,钢筋的海洋会在硝烟中化为尘土。
而那些阴影下的朝阳后裔,将重新统治这个世界
罪恶的本源出自于何?无非是过度的生气
发表于 2023-6-6 11:48:47 | 只看该作者

回复 | 举报

墨言魂靈
CT打算像星系一样,先在Fabric/Quilt上制作一个可玩的版本再做对Forge的兼容调整。
城市喧闹,森林归宿。
终有一天,钢筋的海洋会在硝烟中化为尘土。
而那些阴影下的朝阳后裔,将重新统治这个世界
罪恶的本源出自于何?无非是过度的生气
发表于 2023-6-7 00:34:32 | 只看该作者

回复 | 举报

墨言魂靈
目前“元数据”的完成程度(渲染还没做)
虽然目前翻译键崩了(自己的问题)
城市喧闹,森林归宿。
终有一天,钢筋的海洋会在硝烟中化为尘土。
而那些阴影下的朝阳后裔,将重新统治这个世界
罪恶的本源出自于何?无非是过度的生气
发表于 2023-6-7 08:46:50 | 只看该作者

回复 | 举报

初雪·冰
InkSoul 发表于 2023-6-5 23:48
由于总所周知的Forge注册难问题,所以CT打算重新制作一个基于nbt的“数据值”系统。
这样不仅可以节约注册 ...

优先考虑能跑就行肯定是坏的,过分的语法糖和根本不用语法糖只会增加阅读难度,语法糖不细化也会导致很多细节问题。
高版本的Forge的延迟注册确实蛮烦的,但是也不是没办法做分类设计和生成器制造。每次提到生成器就有种ASM的冲动,或许真的越接近底层越有安全感罢(?

清晨的凤梨闻起来真棒!闻起来就像凤梨一样!
发表于 2023-6-7 09:38:00 | 只看该作者

回复 | 举报

墨言魂靈
QQ酱208628 发表于 2023-6-7 09:38
优先考虑能跑就行肯定是坏的,过分的语法糖和根本不用语法糖只会增加阅读难度,语法糖不细化也会导致很多 ...

但我不会整啊……
最开始的确是因为Forge的问题,但现在似乎是能不能完成的问题了……
Fabric的香草注册方式好整,但Forge我真没什么办法(甚至都不知道该在什么时候注册,每次都因为注册器锁了失败)。
至少先整起来再优化吧,抛开实力谈技术力真的没有意义……

(根本原因就是不会写像GTI/GTCEu那样的模型生成,而datagen一堆文件又太浪费内存【材料一多起来就直接完蛋】,所以就想到把所有物品叠在一个物品上用元数据区分然后一个BlockEntityWithoutLevelRenderer搞定)
城市喧闹,森林归宿。
终有一天,钢筋的海洋会在硝烟中化为尘土。
而那些阴影下的朝阳后裔,将重新统治这个世界
罪恶的本源出自于何?无非是过度的生气
发表于 2023-6-7 09:56:56 | 只看该作者

回复 | 举报

初雪·冰
InkSoul 发表于 2023-6-7 09:56
但我不会整啊……
最开始的确是因为Forge的问题,但现在似乎是能不能完成的问题了……
Fabric的香草注册方 ...

保证你要注册的内容能够在ItemRegister被注册到总线前都在静态变量池中可用,不可以在注册到总线后再注册或者先注册ItemRegister再注册物品这样。换句话说就是因为这个注册是惰性的,只要静态池内可用且不提前调用基本上不太会有大问题这样...  最好的办法就是写到一个类里,会被统一申明。

Fabric的香草注册确实很棒,低版本上来完全没有不适应(


清晨的凤梨闻起来真棒!闻起来就像凤梨一样!
发表于 2023-6-7 10:06:46 | 只看该作者

回复 | 举报

墨言魂靈
本帖最后由 InkSoul 于 2023-6-7 10:15 编辑
QQ酱208628 发表于 2023-6-7 10:06
保证你要注册的内容能够在ItemRegister被注册到总线前都在静态变量池中可用,不可以在注册到总线后再注册 ...

我当时的实现是这样的:public static final DeferredRegister<Block> MATERIAL_BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS,
        CT_Main.MOD_ID);
public static final DeferredRegister<Item> MATERIAL_ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS,
        CT_Main.MOD_ID);

public static void init(final FMLClientSetupEvent event) {
    for (var i : MaterialSet.materials) {
        for (var ii = 0; ii < i.regBlocks.size(); ii++) {
            var iii = ((MaterialBlock) i.regBlocks.get(ii));
            i.regBlocks.set(ii, MATERIAL_BLOCKS
                .register(iii.getMaterial().regName[0] + "_" + iii.getType().regName, () -> iii).get());
        }
        for (var ii = 0; ii < i.regItems.size(); ii++) {
            var iii = ((MaterialItem) i.regItems.get(ii));
            var reg = MATERIAL_ITEMS.register(iii.getMaterial().regName[0] + "_" + iii.getType().regName, () -> iii)
                .get();
            i.partItems.put((iii).getType(), reg);
            i.regItems.set(ii, reg);
        }
    }
    // 获取Mod事件总线
    IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
    // 将物品与方块扔进总线
    MATERIAL_ITEMS.register(bus);
    MATERIAL_BLOCKS.register(bus);
}

public static List<MaterialSet> materials;
public static Map<Item, MaterialSet> vanilaItemMaterial = new HashMap<Item, MaterialSet>();
public static Map<Tag<Item>, MaterialSet> vanilaTagMaterial = new HashMap<Tag<Item>, MaterialSet>();

// ...

private static MaterialSet register(MaterialSet material){
    materials.add(material);
    return material;
}

public static final MaterialSet IRON;
public static final MaterialSet GOLD;

static {
    IRON = register(
        new MaterialSet("Iron", new Settings(0xffffff))
        .addPart(PartType.BLOCK, Blocks.IRON_BLOCK)
        .addPart(PartType.INGOT, Items.IRON_INGOT)
        .addPart(PartType.NUGGET, Items.IRON_NUGGET)
        .regPart(PartType.values())
    );
    GOLD = register(
        new MaterialSet("Gold", new Settings(0x0f0f0f))
        .addPart(PartType.BLOCK, Blocks.GOLD_BLOCK)
        .addPart(PartType.INGOT, Items.GOLD_INGOT)
        .addPart(PartType.NUGGET, Items.GOLD_NUGGET)
        .regPart(PartType.values())
    );
}

反正行不通。

城市喧闹,森林归宿。
终有一天,钢筋的海洋会在硝烟中化为尘土。
而那些阴影下的朝阳后裔,将重新统治这个世界
罪恶的本源出自于何?无非是过度的生气
发表于 2023-6-7 10:12:42 | 只看该作者

回复 | 举报

初雪·冰
InkSoul 发表于 2023-6-7 10:12
我当时的实现是这样的:public static final DeferredRegister MATERIAL_BLOCKS = DeferredRegister.creat ...

为什么注册发生在客户端启动事件里... 以及注册物品至少是服务端上x
客户端概念是游戏的两个线程中的主线程,加入世界的时候会开始分主线程客户端和子线程服务端,而Forge的注册发生在游戏启动的时候... 在Minecraft 1.7.10的时候确实是用FMLInitializationEvent系的事件来呼叫启动注册,但是高版本会直接实例化@Mod注解的类,直接分那个@Mod类的构造方法里注册就好。

清晨的凤梨闻起来真棒!闻起来就像凤梨一样!
发表于 2023-6-7 10:22:47 | 只看该作者

回复 | 举报

百科目前不允许匿名发帖哦~ 请先 [ 登陆 ][ 注册 ] 吧~

本版积分规则

发新帖
  • 回复
  • 点评
  • 评分

[ MC百科(mcmod.cn) 除另有声明,所有开放公共编辑的内容均使用 BY-NC-SA 3.0 协议 ]

Minecraft百科CC协议
快速回复 返回顶部 返回列表