高级项目实例管理问题

时间:2013-02-21 16:38:16

标签: java

我一直在开发一个庞大的角色扮演游戏。问题是我在设计工程时遇到的问题如何管理物料和库存系统。目前我有类似的东西:

  • public abstract class Item有5个嵌套类,它们都是抽象的,静态的,表示Items的类型。每个嵌套类都有一个唯一的use(),delete()(最终确定类实例)和sell()(触发器删除)void。它们还有可选的getter和setter方法,比如setAll()方法,它填充所有必要的字段。
  • 默认:具有基本价格,可交易性布尔值,字符串名称等......非常灵活
  • 武器:除了默认类型所具有的东西之外,它还具有用于装备的stat奖励的整数(用于装备()和非装备()空隙)。与公共阶层英雄互动。
  • 装备:与武器类似,只是它有一个名为“EquipSlot”的枚举字段,用于确定装备的位置。
  • 消耗品:与默认值类似,只是它有一个consume()void,使玩家能够在使用时将某些效果应用于Hero。消费通常意味着触发delete()void。
  • 特别:通常在'Tradeable'布尔值为 static,final,且始终为false 的任务相关项目。

现在,我制作自定义项目的方式就是这样。

  • 首先,我创建一个新类(非抽象)
  • 然后,我将它扩展为Item.ItemType
  • 然后,我创建一个内部具有setAll(info)void的构造函数。
  • 然后,我可以在其他类中使用此类。

这一切看起来像这样:

package com.ep1ccraft.Classes.Items.Defaults;

import com.ep1ccraft.apis.Item.*;

public class ItemExample extends Item.Default {
    public ItemExample() { // Constructor
        this.setAll(lots of arguments here);
    }
}

然后我可以做到:

ItemExample something = new ItemExample();

我有一个完美的ItemExample,包含我想要的所有属性,所以,我可以创建它的各种实例,并使用像'getName()'这样的东西。

问题来命名实例,因为我不知道如何创建一个自动化表单,它将为实例提供与另一个实例不同的名称,这样它们就不会发生冲突。此外,我想实现一个库存系统,它使用插槽作为容器并可以保持堆栈(仅可堆叠项目),它的主要特征是你可以将它们拖放到其他插槽中(例如,重新组织或移动)到另一个库存实例,如银行,或放置在英雄的武器或设备插槽中,如果允许的话)并且您可以单击它们以显示一个屏幕,显示该项目的名称,描述和可能的操作(触发前面提到的delete()和use()空洞)。

感谢您阅读所有内容!我知道也许我要求的太多,但无论如何我都会感激任何答案!

1 个答案:

答案 0 :(得分:0)

所以基本上,你要求为你的对象提供一个唯一的标识符。可能有无数的方法,但立即想到的三种不同的方法是:

1:UUID;类似的东西:

java.util.UUID.randomUUID()

优点:一个非常非常简单的解决方案......

缺点:它会生成大量字节(16 +对象本身),占用内存/磁盘存储空间,这可能是MMO中的一个问题

2:全球运行数;类似的东西:

class ID {
    private static volatile long id = 0;
    public synchronized long nextId() {
        return id++;
    }
}

优点:同样,一个简单的解决方案......

缺点:即使这是一个非常简单的类,它确实包含“volatile”和“synchronized”,这可能是MMO的一个问题,特别是如果它被大量使用。此外,如果你的数字用完了,在X年的运行时间后会发生什么。 64位长确实需要创建很多命名对象,毕竟它可能不是问题......你必须自己做数学。

3:命名为全球运行数字;类似的东西:

class NamedID {
    private static volatile Map<String, Long> idMap = new HashMap<String, Long>();
    public synchronized long nextId(String name) {
        Long id = idMap.get(name);
        if (id == null) {
            id = 0;
        } else {
            id++;
        }
        idMap.put(name, id);
        return id;
    }
}

优点:您可以将ID“本地化”为您正在使用的任何名称。

缺点:一个更复杂的解决方案,在速度方面比“2”差,因为同步持续时间更长。

注意:我无法弄清楚如何更快地提出这个最后的建议;我想过使用ConcurrentHashMap,但这不起作用,因为它在较低的层次上工作;即,它不能保证两个线程不会在idMap.getidMap.put语句之间相互干扰。