I've been developing a massive Role Playing Game. The problem is that I'm having trouble engineering how will I manage the Item and Inventory system. Currently I have something similar to this:
public abstract class Item has 5 Nested classes which all are abstract and static that represent the types of Items. Every Nested class has an unique use(), delete() (Which finalizes the class instance) and sell()(triggers delete) void. They also have optional getter and setter methods, like the setAll() method which fills all necesary fields.
Default: Has base price, tradeability boolean, String name, etc... Very flexible
Weapon: Else than the things that the Default type has, it has integers for stat bonus on being equipped(used in the equip() and unequip() voids). Interacts with public class Hero.
Equipment: Similar to Weapon, just that it has an Enum field called 'EquipSlot' that determines where it is equipped.
Consumable: Similar to default, just that has a consume() void that enables the player to apply certain effects to an Hero when using it. Consuming usually means triggering the delete() void.
Special: Usually quest related items where the 'Tradeable' boolean is static, final and always false.
Now, the way that I make customized items is this.
First, I make a new class (Not abstract)
Then, I make it extend Item.ItemType
Then, I make a constructor which has the setAll(info) void inside.
Then, I can use this class in other classes.
It all looks like this:
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);
}
}
then I can do:
ItemExample something = new ItemExample();
And I have a perfect ItemExample with all the properties that I want, So, I can make various instances of it, and use amazing methods like 'getName()' and that kind of stuff.
The problems come to Naming the instances, as I do not know how to make an automated form that will give the instance a Different name from the other instance so they don't collide. Also, I want to implement an inventory system that uses slots as containers and can keep stacks (Stackable items only), also the main feature of it is that you can drag and drop them into other slots (For example, to reorganize or to move to another inventory instance like a bank, or to place in an hero's weapon or equipment slots, if it is allowed) and that you can click on them to display a screen that shows the name, description and possible actions of the Item (Which trigger the previously mentioned delete() and use() voids).
Thank you for reading all that! I know that maybe I'm asking for too much, but I'll appreciate any answers anyway!
So basically, you're asking for a unique identifier for your object. There are probably countless approaches to this, but the three different approaches that immediately come to mind are:
1: A UUID; something like:
java.util.UUID.randomUUID()
Pros: A very, very simple solution...
Cons: It does generate a large amount of bytes (16 + the object itself), taking memory / disk storage, which might be an issue in a MMO
2: A global running number; something like:
class ID {
private static volatile long id = 0;
public synchronized long nextId() {
return id++;
}
}
Pros: Again, a simple solution...
Cons: Even though this is a very simple class, it does contain "volatile" and "synchronized", which might be an issue for an MMO, especially if it is used heavily. Also, What happens after X years of running time, if you run out of numbers. A 64 bit long does require quite a lot of named objects to be created, it may not be an issue after all... you'll have to do the math yourself.
3: Named global running numbers; something like:
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;
}
}
Pros: You get id's "localized" to whatever name you're using for it.
Cons: A bit more complex solution, and worse than "2" in terms of speed, since the synchronzation lasts longer.
Note: I couldn't figure out how to make this last suggestion faster; i thought of using a ConcurrentHashMap, but that won't work since it works on a lower level; i.e. it will not guarantee that two thread does not interfere with each other between the idMap.get and the idMap.put statements.
Related
Consider this database model:
Book
isbn primary key
title
In a RDBMS, the database makes sure that two identical rows don't exist for the above model.
Similarly, in Java consider this object model:
Book
- isbn: int
- title: String
+ Book(isbn)
Let's say we are creating a Book object:
Book b = new Book(123456);
Later, in some other part of the code we are creating again an identical Book object:
Book c = new Book(123456);
Can Java make sure that no two objects exist in the JVM heap if they are identical? Just like a RDBMS does?
There's no built-in mechanism in Java that automatically does this for you. You could build something for this, but probably shouldn't. And if you do, then probably not in the way that you show in your question.
First: let's assume that these objects are immutable, so the problem is reduced to "let no two objects be constructed that have the same attributes". This is not a necessary restriction, but this way I can already demonstrate the issues with this approach.
The first issue is that it requires you to keep track of each Book instance in your program in a single central place. You can do that quite easily by having a collection that you fill when an object is constructed.
However, this basically builds a massive memory leak into your program because if nothing else hangs on to this Book object, that collection still will reference it, preventing it from being garbage collected.
You can work around that issue by using WeakReference object to hold on to your Book objects.
Next, if you want to avoid duplicates, you almost certainly want a way to fetch the "original" instance of a Book if you can't create a new one. You can't do that if you simply use the constructor, since the constructor can't "return another object", it will always create and return a new object.
So instead of new Book(12345) you want something like BookFactory.getOrCreateBook(12345). That factory can then either fetch the existing Book object with the given id or create a new one, as required.
One way to make the memory leak issue easier to handle (and also to potentially allow multiple parallel sessions each with their own set of unique Book objects) is to make the BookFactory be a BookSession: i.e. you instantiate one and it keeps tracks of its books. Now that BookSession is the "root" of all Books and if it no longer gets referenced it (and all the books it created) can potentially be garbage collected.
All of this doesn't even get into thread safety which is solvable reasonably easily for immutable objects but can get quite convoluted if you want to allow modifications while still maintaining uniqueness.
A simple BookSession could look a little like this (note that I use a record for book only for brevity of this sample code, this would leave the constructor visible. In "real" code I'd use an equivalent normal class where the constructor isn't accessible to others):
record Book(int isbn, String title) {}
class BookSession {
private final ConcurrentHashMap<Integer, Book> books = new ConcurrentHashMap<>();
public Optional<Book> get(int isbn) {
return Optional.ofNullable(books.get(isbn));
}
public Book getOrCreate(int isbn, String title) {
return books.computeIfAbsent(isbn, (i) -> new Book(i, title));
}
}
You can easily add other methods to the session (such as findByTitle or something like that).
And if you only ever want a single BookSession you could even have a public static final BookSession BOOKS somewhere, if you wanted (but at that point you have re-created the memory leak)
I do not know of a JVM internals specific way of doing this, but it is not that hard to achieve the basic goal. Joachim Sauer's answer goes into depth on why this might not be the greatest idea without some additional forethought :)
If you forego of thread safety, the code is basically just about creating a private constructor and use a factory method that keeps tab on created objects.
Pseudo Java follows
public class Book {
// potential memory leak, see Joachim Sauer's answer (WeakReference)
Map<Book> created = new Map<>();
// other internal fields follow
// can only be invoked from factory method
private Book(String isbn){ /* internals */ }
public Book get(String isbn){
if(created.has(isbn)) return created.get(isbn);
var b = new Book(isbn);
b.add(isbn, b);
return b;
}
}
Converting this to a thread safe implementation is just about adding some details * and is another question. Avoiding the potential memory leak means reading up on weak references.
i.e. locks (synchronized), mutexes, Concurrent*, Atomic*, etc
Neither of the other answers is technically correct.
They will often work, but in situations where multiple ClassLoaders are in play they will both fail.
Any object instance can ever only be unique within the context of a specific ClassLoader, thus 2 instances of the same Book can exist, even if you guard against multiples being created within a specific ClassLoader.
Usually this won't be a problem as many (especially simpler) programs will never have to deal with multiple ClassLoaders existing at the same time.
There is btw no real way to protect against this.
I'm not sure how to name this question but I tried my best. We have a table in the database with rows representing mappings, each row has a string column that specify what object corresponds to. For example some rows have 'Books' in that column, others have 'CDs', other have 'Paintings' etc.
We want to retrieve all rows associated to a specific kind of object, for example all rows associated with 'Books'. We have a class that serves that table.
We have two ways to write that class. Which option is better? (some Option 3 maybe? There is no preferred way? It doesn't matter? Genuinely curious.)
Option 1
public TableClass {
public List<Field> getBooksFields() {
return getFields('Books');
}
public List<Field> getCDsFields() {
return getFields('CDs');
}
...etc...
private List<Field> getFields(String name_of_field) {
return tableRepository.getRowsWithType(name_of_field);
}
}
And then everywhere in the code where we want to get the fields associated to books, we can just do:
List<Field> bookFields = tableClass.getBooksFields();
Option 2
public TableClass {
public List<Field> getFieldsWithType(String name_of_field) {
return tableRepository.getRowsWithType(name_of_field);
}
...
}
And then hardcode in a Constants static class, the name associated to each field in the database. So we would do:
import Constants.BOOKS_FIELD_NAME;
...
List<Field> bookFields = tableClass.getFields(BOOKS_FIELD_NAME);
Which option is better from a coding perspective??
My short answer to this question would be - Whatever you like the most. Because you call one more function, even though you won't (always) have a big impact on performance, there is some impact.
Mostly compiler will just inline your second function but if this doesn't happen then you are losing some performance. But I need to say that this is not that much and you won't even notice it if your code is nicely written.
What you want is to write code that is understandable and clean for everyone using it later and there is one other question here. Are there possibilities that your database query would need changes in keywords like 'Books'? It is always easier to change this in one place (1st option) than going through code and changing it more than once (search and replace - yes but still takes more time).
It is really up to you, both codes are nice. The second one is cleaner and easier to edit but the first one is more optimized (not that much).
More about calling functions from functions you can read here in this answer: https://stackoverflow.com/a/27875180/14759470
I am writing RaspberryPi program for executing tasks at given time. I wrote TaskManager that keeps all tasks in synchronized Map (awaitingTasks) and manage them. One of it's methods is
addInTimeTasks(...)
public static int addInTimeTask(Callable task, DateTime time) {
synchronized (awaitingTasks) {
final int id = assignNewId();
awaitingTasks.put(id, scheduledThreadPool.schedule(new CallableTask(task, new CallableTask.MyCallback() {
#Override
public void onFinish() {
awaitingTasks.remove(id);
}
}), TimeDiffCalc.secToDate(time), TimeUnit.SECONDS));
return id;
}
}
as you can see Task (thinking of making it class if it has more attributes) have its own ID, Date and method that it executes.
I want to handle situation when server restarts and all in time tasks simply dissapear. I was thinking about holding Tasks in database. I can hold TaskID and Date but how do I determine method that given task should execute?
I like flexablity of this method cuz I can make any method in-time executable.
For example here is method from RGBLed class (which have mutltiple methods that can be executed in time)
public int lightLed(final LedColor color, DateTime dateTime){
return TaskManager.addInTimeTask(new Callable<Void>() {
public Void call() throws Exception {
//here is code that makes led lighting
return null;
}
},dateTime);
}
What came into my mind was to assign to every method ID, and then get method by id but I dont think it is passible.
I ll bet that were many questions with similar problem but I can not simply find them. I can not specify question properly (So please change it)
Thanks!
You are facing two problems. That one that you describe can be fixed "easily". You see, you know that you want to call specific methods.
Methods have names. Names are ... strings. So, you could simply store that name as string; and when you have some object in front of you, you can use Java reflection means to invoke a particular method.
The other problem is: persisting your objects might not be that easy. If I get your examples right, you are mostly dealing with anonymous inner classes. And yes, objects of such classes can be serialized too, but not as "easy" or "without thought" as normal classes (see here for example).
So, my suggestions:
Don't use inner classes; but ordinary classes (although that might affect the "layout" of existing code to a great degree); serialize objects of those classes
Together with serialized object, remember name (and probably the arguments you need) so you can call methods by name
Probably it would make sense to create a class specifically for that purpose; containing two fields (the actual object to serialized, and the name of the method to call on that).
I'm trying to make a class which represents an Ability of a Champion in my game. The impediment I've faced is that I don't know how to design an Ability class with multiple properties i.e. damaging, stuning, slowing. My idea was to create enum class which represents all these properties and then assign them to my abilities, for example:
public enum Effect {
DAMAGE,
SLOW,
STUN,
...
}
But what if I have an ability that stuns and deals damage at the same time? Should I create an Effect[] array and to deal with it somehow or should I create interface-markers like Serializable(it's the creaziest idea I've had)? Or maybe there is some technique for cases like that?
An array with Effect objects seems fine, a list would be even better. You can even create your own wrapper class to provide additional methods calculating entity properties based on applied effects.
For example:
public class Effects
{
public int calculateDamage(int baseDamage)
{
int damage = baseDamage;
if (effects.contains(Effect.DAMAGE)) {
// some effect stacking :)
damage *= 1.5 * Collections.frequency(effects, Effect.DAMAGE);
}
if (effects.contains(Effect.STUN)) {
damage = 0;
}
return damage;
}
private final List<Effect> effects = new ArrayList<>();
}
Collections.frequency() is a utility method from Apache Commons library, which I highly recommend.
you can create a class of type Effect with all properties as Boolean attributes and then assign true or false to them as you like, and if you like to extend properties to ones you can't decide at compile time think about putting one hashmap of type HashMap in Effect class
My application will upon request retrieve information from a database and produce an object from that information. I'm currently considering two different techniques (but I'm open to others as well!) to complete this task:
Method one:
class Book {
private int id;
private String author;
private String title;
public Book(int id) {
ResultSet book = getBookFromDatabaseById(id);
this.id = book.id;
this.author = book.author;
// ...
}
}
Method two:
public class Book {
private HashMap<String, Object> propertyContainer;
public Book(int id) {
this.propertyContainer = getBookFromDatabaseById(id);
}
public Object getProperty(String propertyKey) {
return this.propertyContainer.get(propertyKey);
}
}
With method one, I believe that it's easier to control, limit and possibly access properties, adding new properties, however, becomes smoother with method two.
What's the proper way to do this?
I think this problem has been solved in many ways: ORM, DAO, row and table mapper, lots of others. There's no need to redo it again.
One issue you have to think hard about is coupling and cyclic dependencies between packages. You might think you're doing something clever by telling a model object how to persist itself, but one consequence of this design choice is coupling between model objects and the persistence tier. You can't use model objects without persistence if you do this. They really become one big, unwieldy package. There's no layering.
Another choice is to have model objects remain oblivious to whether or not they're persisted. It's a one way dependence that way: persistence knows about model objects, but not the other way around.
Google for those other solutions. There's no need to beat that dead horse again.
The first method will provide you with type safety for associated accessors so you will know what type of object you are getting back and don.t have to cast to that type the you are expecting (this becomes more important when providing anything other than primitives).
For that reason (plus that it will make the resulting code simpler and easier to read) I would pick the first one. In any large applications you will also be able to quickly, easily and neatly get parameter values back in the code for debug etc. within the object itself.
If anyone else is going to be working on this code also (or your planning on working it after you forget about it) the first one will also help as you know the parameters etc. The second one will only give you this with extensive javadoc.
The first one is the classical way. The second one is really tricky for nothing.