Basic Question about reference variable

Results 1 to 7 of 7
  1. #1
    The journey never ends. SYJourney is offline
    MemberRank
    Mar 2015 Join Date
    FrankfurtLocation
    427Posts

    Basic Question about reference variable

    Hello ragezone,
    if I do this:
    Code:
        private final MapleMapData mapData;
        
        private final byte world, channel;
        
        public newMapleMap(int mapid, byte channel, byte world) {
            this.world = world;
            this.channel = channel;
            mapData = MapleMapDataFactory.getInstance().getMapData(mapid);
        }
        
        public int getId() {
            return mapData.getId();
        }
    MapleMapData should only be a reference from what I've read.
    If I now make multiple objects of maplemap, will they all reference the same MapleMapData?

    Channel 1: MapleMap --v
    Channel 2: MapleMap -----> MapleMapData
    Channel 3: MapleMap --^

    I want to be 100% sure that it works this way inb4 I have multiple copies of MapleMapData. All the data store in there is supposed to be constant, and channel-independent.

    I tried using the profiler to find this out, but I don't seem to have it setup correctly. It kept showing only one MapleMap object even when multi-clienting.

    Edit: I should add, getMapData() tries to get a MapleMapData from a HashMap, if the Hashmap doesn't contain the mapid, it loads it from xml files, caches and returns.


  2. #2
    BloopBloop Hilia is offline
    MemberRank
    Aug 2012 Join Date
    905Posts

    Re: Basic Question about reference variable

    EDIT:(The first two parts where so unneeded that i only kept the third part)

    (Now with MapleMapData i assume that you mean that you splitted the MapleMap.java class in two classes: MapleMapData, with the basic map data and MapleMap, containing the MapleData class and the things that have to be separated by each channel)


    In this case i would suggest to use the MapleMapData.java in a special Singleton based MapleMapDataProvider. Now every channel does still need to have his/her own instance of a MapleMap,(Every channel does have his own map,with his own list of characters) (so that means that you still need to create new Maps for every channel),although that doesn't mean that every channel needs his/her own instance of the MapleMapData, since those data is the same for every channel with the same mapID.
    In other words:Below is a small example of the code that you want.

    Where as: MapleMapDataProvider = a Singleton, and so on it creates and "parses" the MapleMapData only ONCE, (meaning that not every channel keeps parsesing the same shit and wastes a SHITLOAD OF MEMORY)

    Where as: MapleMapProvider = a simply provider class that makes sure that every channel still has his own map.

    So in other words: This would be the best design,and would safe a lot or memory:
    Spoiler:

    Code:
       static void Main(string[] args)
            {
    
    
                var c1 = new Channel();
                var c2 = new Channel();
    
    
                Console.WriteLine(c1.GetMap(1) == c2.GetMap(1)); // FALSE
                Console.WriteLine(c1.GetMap(1).mData == c2.GetMap(1).mData); //TRUE
    
    
                Console.ReadLine();
            }
        }
    
    
        public class Channel
        {
            private readonly MapleMapProvider mProvider;
    
    
            public Channel()
            {
                mProvider = new MapleMapProvider();
            }
    
    
            public MapleMap GetMap(int ID)
            {
                return mProvider.GetMap(ID);
            }
        }
    
    
        public class MapleMapProvider
        {
            private readonly Dictionary<int, MapleMap> mMaps;
    
    
            public MapleMapProvider()
            {
                mMaps = new Dictionary<int, MapleMap>();
                mMaps.Add(1, new MapleMap(1));
                mMaps.Add(2, new MapleMap(2));
            }
    
    
            public MapleMap GetMap(int ID)
            {
                return mMaps[ID];
            }
        }
    
    
    
    
        public class MapleMap
        {
            public readonly MapleMapData mData;
            private readonly List<Character> mCharacters;
    
    
            public MapleMap(int MapID)
            {
                mData = MapleMapDataProvider.Instance.GetData(MapID);
                mCharacters = new List<Character>();
            }
    
    
    
    
        }
    
    
    
    
        public class MapleMapData
        {
            private readonly int mReturnMap;
            private readonly string mName;
    
    
            public MapleMapData(int ReturnMap, string Name)
            {
                mReturnMap = ReturnMap;
                mName = Name;
            }
    
    
            public string Name
            {
                get { return mName; }
            }
    
    
            public int ReturnMap
            {
                get { return mReturnMap; }
            }
        }
    
    
        public class MapleMapDataProvider
        {
            public static readonly MapleMapDataProvider Instance;
            private static readonly Dictionary<int, MapleMapData> mMapData;
            
            static MapleMapDataProvider()
            {
                Instance = new MapleMapDataProvider();
                mMapData = new Dictionary<int, MapleMapData>();
                mMapData.Add(1, new MapleMapData(1, "Henesys")); //IDK the ID
                mMapData.Add(2, new MapleMapData(2, "Perion"));
            }
    
    
            public MapleMapData GetData(int MapID)
            {
                return mMapData[MapID];
            }
        }
    
    
        public class Character
        {
           
    
    
         }
    
    
    }
    Last edited by Hilia; 20-06-15 at 10:11 PM.

  3. #3
    The journey never ends. SYJourney is offline
    MemberRank
    Mar 2015 Join Date
    FrankfurtLocation
    427Posts

    Re: Basic Question about reference variable

    Thanks alot for your reply! I think I have the same basic setup:

    MapleMapDataFactory:
    Code:
    private static final Map<Integer, MapleMapData> mapdata = new HashMap<>();
        
        private static MapleMapDataFactory instance;
        private final ReentrantLock dataLoadLock;
    
        private MapleMapDataFactory() {
            this.source = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz")); 
            this.nameData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz")).getData("Map.img");
            dataLoadLock = new ReentrantLock(false);
        }
        
        public static MapleMapDataFactory getInstance() {
            if (instance == null) {
                instance = new MapleMapDataFactory();
            }
            return instance;
        }
        
        public boolean isMapDataLoaded(int mapid) {
            return mapdata.containsKey(mapid);
        }
    
        public MapleMapData getMapData(int mapid) {
            if (mapdata.containsKey(mapid)) {
                return mapdata.get(mapid);
            } else  {
                dataLoadLock.lock();
                try { and so on...
    MapleMapData:
    Code:
    private final Map<Byte, MaplePortal> portals = new HashMap<>();
        private Pair<Integer, String> timeMob;
        private final Map<Integer, MapleMapObject> mapobjects = new HashMap<>();
        
        private MapleFootholdTree footholds = null;
        
        public MapleMapData(int mapid, int returnMapId, int forcedReturnId,  float monsterRate, String onEnterF, String onEnter, int fieldType, int fieldLimit, int mobCapacity, short mobInterval, boolean clock, boolean town, boolean everlast, boolean boat, int decHp, int protectItem, int timeLimit) {
            this.mapid = mapid;
            this.returnMapId = returnMapId;
            ...and so on
    MapleMapFactory:
    Code:
    public MapleMap getMap(int mapid) {
            if (maps.containsKey(mapid)) {
                return maps.get(mapid);
            } else {
                mapLoadLock.lock();
                try {
                    if (maps.containsKey(mapid)) {
                        return maps.get(mapid);
                    }
                    final MapleMap map = new MapleMap(mapid, world, channel);
                    
                    MapleMapData data = MapleMapDataFactory.getInstance().getMapData(mapid);
                    map.setTimeLimit(data.getTimeLimit());
                    
                    if (AreaBossFactory.hasBoss(map.getId())) {
                        AreaBossData ab = AreaBossFactory.getBossData(map.getId());
                        map.addBossSpawn(MapleLifeFactory.getMonster(ab.getId()), data.calcBossSpawnPosition(ab.getPosition()), ab.getIntervall(), ab.getMsg());
                    }
                    
                    data.getMapObjects().stream().forEach((mmo) -> {
                        if (mmo instanceof MapleMonster) {
                            MapleMonster mob = (MapleMonster) mmo;
                            if (mob.getMobtime() == -1) {
                                map.spawnMonster(mob);
                      ...and so on
    I'm assuming readonly = final?
    Also is there a reason why mapData in maplemap is public? Can it be private + getter Method, or will that cause the memory waste?

  4. #4
    BloopBloop Hilia is offline
    MemberRank
    Aug 2012 Join Date
    905Posts

    Re: Basic Question about reference variable

    Quote Originally Posted by SYJourney View Post
    Thanks alot for your reply! I think I have the same basic setup:

    MapleMapDataFactory:
    Code:
    private static final Map<Integer, MapleMapData> mapdata = new HashMap<>();
        
        private static MapleMapDataFactory instance;
        private final ReentrantLock dataLoadLock;
    
        private MapleMapDataFactory() {
            this.source = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz")); 
            this.nameData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz")).getData("Map.img");
            dataLoadLock = new ReentrantLock(false);
        }
        
        public static MapleMapDataFactory getInstance() {
            if (instance == null) {
                instance = new MapleMapDataFactory();
            }
            return instance;
        }
        
        public boolean isMapDataLoaded(int mapid) {
            return mapdata.containsKey(mapid);
        }
    
        public MapleMapData getMapData(int mapid) {
            if (mapdata.containsKey(mapid)) {
                return mapdata.get(mapid);
            } else  {
                dataLoadLock.lock();
                try { and so on...
    MapleMapData:
    Code:
    private final Map<Byte, MaplePortal> portals = new HashMap<>();
        private Pair<Integer, String> timeMob;
        private final Map<Integer, MapleMapObject> mapobjects = new HashMap<>();
        
        private MapleFootholdTree footholds = null;
        
        public MapleMapData(int mapid, int returnMapId, int forcedReturnId,  float monsterRate, String onEnterF, String onEnter, int fieldType, int fieldLimit, int mobCapacity, short mobInterval, boolean clock, boolean town, boolean everlast, boolean boat, int decHp, int protectItem, int timeLimit) {
            this.mapid = mapid;
            this.returnMapId = returnMapId;
            ...and so on
    MapleMapFactory:
    Code:
    public MapleMap getMap(int mapid) {
            if (maps.containsKey(mapid)) {
                return maps.get(mapid);
            } else {
                mapLoadLock.lock();
                try {
                    if (maps.containsKey(mapid)) {
                        return maps.get(mapid);
                    }
                    final MapleMap map = new MapleMap(mapid, world, channel);
                    
                    MapleMapData data = MapleMapDataFactory.getInstance().getMapData(mapid);
                    map.setTimeLimit(data.getTimeLimit());
                    
                    if (AreaBossFactory.hasBoss(map.getId())) {
                        AreaBossData ab = AreaBossFactory.getBossData(map.getId());
                        map.addBossSpawn(MapleLifeFactory.getMonster(ab.getId()), data.calcBossSpawnPosition(ab.getPosition()), ab.getIntervall(), ab.getMsg());
                    }
                    
                    data.getMapObjects().stream().forEach((mmo) -> {
                        if (mmo instanceof MapleMonster) {
                            MapleMonster mob = (MapleMonster) mmo;
                            if (mob.getMobtime() == -1) {
                                map.spawnMonster(mob);
                      ...and so on
    I'm assuming readonly = final?
    Also is there a reason why mapData in maplemap is public? Can it be private + getter Method, or will that cause the memory waste?
    Readonly = final (kinda, but for most of the time it is correct)
    And yes MapData can be private , i was just to lazy to write another Get method,the "Get Method" its self will not waste any "memory" (Ram).

    So i did "scan" thought the code you provided. Your code seems good, (including the locks).
    However i would advice to make everything final (readonly) in MapleMapData since well, if you do this structure don't even think about it to include one or more set methods since that will fuck up everything, The best would be to only use the constructor to fill the class ,what allows you to make everything final. Then add a lot of get methods in that class to get those readonly (final) value's
    Last edited by Hilia; 20-06-15 at 10:29 PM.

  5. #5
    The journey never ends. SYJourney is offline
    MemberRank
    Mar 2015 Join Date
    FrankfurtLocation
    427Posts

    Re: Basic Question about reference variable

    Quote Originally Posted by Hilia View Post
    (i didn't rad the code you posted for now xD)
    I'm perfectly ok with that, you already did your job by actually replying.
    Tbh I wasn't excepting to get any help with this in this forum :P

  6. #6
    BloopBloop Hilia is offline
    MemberRank
    Aug 2012 Join Date
    905Posts

    Re: Basic Question about reference variable

    Quote Originally Posted by SYJourney View Post
    I'm perfectly ok with that, you already did your job by actually replying.
    Tbh I wasn't excepting to get any help with this in this forum :P
    I have read it by now and made a small edit,but this is indeed the best structure for MoopleDEV to save "some" memory, since all the channels are in one console.

  7. #7
    Account Upgraded | Title Enabled! Syre is offline
    MemberRank
    Jan 2013 Join Date
    700Posts

    Re: Basic Question about reference variable

    An actual useful help subject. I saw who the OP was and got a little excited, tbh. I even learned from this, so thank you hilia.



Advertisement