Thread: [Kronos] Removing Forum Login, Fixing Friends Chat and Clan Chat, Password Saving

Page 1 of 2 12 LastLast
Results 1 to 10 of 19
  1. #1 [Kronos] Removing Forum Login, Fixing Friends Chat and Clan Chat, Password Saving 
    RuneCasino


    Join Date
    Jul 2007
    Posts
    1,647
    Thanks given
    175
    Thanks received
    257
    Rep Power
    358
    As the title says, this is for Removing Forum Login, Fixing Friends Chat and Clan Chat and adding Password Saving.

    Lots of people asked for this so I thought I would release.

    Do not use the old thread I made about removing forum login and UNDO any changes that you made.
    It is recommended that you re-download Kronos if you used that tutorial.

    Server must have offline mode set to FALSE

    The purpose of this is to use central server (friends/clan chat) without using forum settings.

    If you don't have mysql databases set up you must comment out or delete these lines in [io.ruin > Server.java] (kronos-server files)

    Code:
                siteDb = new Database(properties.getProperty("database_host"), "kronos", properties.getProperty("database_user"), properties.getProperty("database_password"));
                gameDb = new Database(properties.getProperty("database_host"), "game", properties.getProperty("database_user"), properties.getProperty("database_password"));
                forumDb = new Database(properties.getProperty("database_host"), "community", properties.getProperty("database_user"), properties.getProperty("database_password"));
    
                DatabaseUtils.connect(new Database[]{gameDb, forumDb, siteDb}, errors -> {
                    if (!errors.isEmpty()) {
                        for (Throwable t : errors)
                            logError("Database error", t);
                        System.exit(1);
                    }
                });
    Step One: Removing Forum Login

    REQUIRED FOR FIXING FRIENDS CHAT AND CLAN CHAT

    This is for removing forum login so you can use the central server or else you wouldn't be able to use the central server features (Clan/Friends chat).

    Go to io.ruin.central.model.world > WorldLogin.java (kronos-central-server)

    Replace everything with this:

    Code:
    package io.ruin.central.model.world;
    
    import com.google.gson.JsonObject;
    import io.ruin.api.protocol.Protocol;
    import io.ruin.api.protocol.Response;
    import io.ruin.api.protocol.login.LoginInfo;
    import io.ruin.api.protocol.login.LoginRequest;
    import io.ruin.api.utils.*;
    import io.ruin.central.Server;
    import io.ruin.central.model.Player;
    import io.ruin.central.utility.XenforoUtils;
    import io.ruin.model.entity.player.PlayerGroup;
    import lombok.extern.slf4j.Slf4j;
    import org.json.JSONArray;
    import org.json.JSONObject;
    
    import java.util.ArrayList;
    import java.util.concurrent.CompletableFuture;
    
    @Slf4j
    public class WorldLogin extends LoginRequest {
    
        private World world;
    
        public static String capitalize(String s) {
            s = s.toLowerCase();
            s = s.replaceAll("_", " ");
            for (int i = 0; i < s.length(); i++) {
                if (i == 0) {
                    s = String.format("%s%s", Character.toUpperCase(s.charAt(0)), s.substring(1));
                }
                if (!Character.isLetterOrDigit(s.charAt(i))) {
                    if (i + 1 < s.length()) {
                        s = String.format("%s%s%s", s.subSequence(0, i+1), Character.toUpperCase(s.charAt(i + 1)), s.substring(i+2));
                    }
                }
            }
            return s;
        }
    
        public WorldLogin(World world, LoginInfo info) {
            super(info);
            this.world = world;
    
            if (UUIDBan.isUUIDBanned(info.uuid) || IPBans.isIPBanned(info.ipAddress) || MACBan.isMACBanned(info.macAddress)) {
                this.deny(Response.DISABLED_ACCOUNT);
                return;
            }
    
          /*  CompletableFuture.runAsync(() -> {
    
                    System.err.println(info.name + " attempting to login.");
    
                    JSONObject result = XenforoUtils.attemptLogin(info.name, info.password, info.ipAddress);
    
                    //Should never happen unless website is down
                    if (result == null) {
                        this.deny(Response.LOGIN_SERVER_NO_REPLY);
                        return;
                    }
    
                    String login_code = result.getString("login_code");
                    System.err.println(info.name + " : " + login_code);
    
                    if (login_code.endsWith("could not be found.")) {
                        this.deny(Response.EMAIL_REQUIRED);
                        return;
                    }
                    switch (login_code) {
                        case "Unregistered account.": {
                            this.deny(Response.UNREGISTERED_ACCOUNT);
                            return;
                        }
                        case "Email required.": {
                            this.deny(Response.EMAIL_REQUIRED);
                            return;
                        }
                        case "Email in use.": {
                            this.deny(Response.EMAIL_IN_USE);
                            return;
                        }
                        case "Username too long.": {
                            this.deny(Response.USERNAME_TOO_LONG);
                            return;
                        }
                        case "Username contained disallowed words.": {
                            this.deny(Response.USERNAME_BAD_WORDS);
                            return;
                        }
                        case "Username contains incorrect characters.": {
                            this.deny(Response.USERNAME_BAD_LETTERS);
                            return;
                        }
                        case "Incorrect password. Please try again.": {
                            this.deny(Response.INVALID_LOGIN);
                            return;
                        }
                        case "Your account has temporarily been locked due to failed login attempts.": {
                            this.deny(Response.LOGIN_LIMIT);
                            return;
                        }
                        case "Two-factor authentication required.": {
                            this.deny(Response.TWO_FACTOR);
                            return;
                        }
                        case "Two-factor authentication limit reached!": {
                            this.deny(Response.LOGIN_LIMIT);
                            return;
                        }
                        case "Two-factor authentication invalid!": {
                            this.deny(Response.TWO_FACTOR_RETRY);
                            return;
                        }
                        case "Banned": {
                            this.deny(Response.DISABLED_ACCOUNT);
                            return;
                        }
                        case "IP Banned": {
                            this.deny(Response.DISABLED_ACCOUNT);
                            return;
                        }
                        case "Username on hold": {
                            this.deny(Response.USERNAME_ON_HOLD);
                            return;
                        }
                        case "Proxy login attempt": {
                            this.deny(Response.PROXY_LOGIN_ATTEMPT);
                            return;
                        }
                    }
                    try {
                        JSONObject user = result.getJSONObject("user");
                        int userId = user.getInt("user_id");
                        String username = user.getString("username");
                        int primaryGroupId = user.getInt("user_group_id");
                        String secondaryGroupIds = String.valueOf(user.getJSONArray("secondary_group_ids"));
                        //int unreadPms = user.get("conversations_unread").getAsInt();
                        if (Protocol.method360(username) == null) {
                            this.deny(Response.CHANGE_DISPLAY_NAME);
                            return;
                        }
                        ArrayList<Integer> groupIds = new ArrayList<Integer>();
                        groupIds.add(primaryGroupId);
                        for (String id : secondaryGroupIds.replace("[", "").replace("]", "").replace("\"", "").split(",")) {  //["10", "10"]
                            try {
                                groupIds.add(Integer.valueOf(id));
                            } catch (Exception exception) {
                                // empty catch block
                            }
                        }
                        for (int i : groupIds) {
                            if (i == 18) {
                                this.deny(Response.DISABLED_ACCOUNT);
                                return;
                            }
                        }*/
                        try {
                            String username = capitalize(info.name);
                            int index = -1;
                            for(int i = 1; i < 2048; i++) {
                                Player player = Server.getPlayer(i);
                                if(player == null) {
                                    index = i;
                                    break;
                                }
                            }
                            if(index != -1) {
                                String saved = Player.load(username, world);
                                info.update(index, username, saved, ListUtils.toList(PlayerGroup.ADMINISTRATOR.id), 0);
                                this.success();
                            } else {
                                this.deny(Response.WORLD_FULL);
                            }
                        } catch (Exception e) {
                            Server.logError(e.getMessage());
                            this.deny(Response.ERROR_LOADING_ACCOUNT);
                        }
              //  }
          //  );
        }
    
        @Override
        public void success() {
            this.world.logins.offer(this.info);
        }
    
        @Override
        public void deny(Response response) {
            this.world.sendLoginFailed(this.info.name, response);
            super.deny(response);
        }
    }
    Now go to io.ruin.model.entity.player > PlayerLogin.java

    Find this:

    Code:
      private void send() {
            if(OfflineMode.loadPlayer(this))
                return;
            CentralClient.sendLogin(info.ipAddress, info.name, info.password, info.email, info.macAddress, info.uuid, info.tfaCode, info.tfaTrust, info.tfaTrustValue & 0xff);
        }
    Replace with:

    Code:
     private void send() {
            info.name = info.name.replaceAll("_", " ");
            if(OfflineMode.loadPlayer(this))
                return;
            CentralClient.sendLogin(info.ipAddress, info.name, info.password, info.email, info.macAddress, info.uuid, info.tfaCode, info.tfaTrust, info.tfaTrustValue & 0xff);
        }
    Now go to io.ruin.central > Server.java

    Find:

    Code:
        
         public static boolean isOnline(int userId, String name) {
            int limboWorld = Limbo.get(userId);
            if (limboWorld != -1) {
                System.err.println(name + " is in limbo on world " + limboWorld + "!");
                return true;
            }
            for (World world : worlds) {
                if (!world.hasPlayer(userId)) continue;
                System.err.println(name + " is online in world " + world.id + "!");
                world.sendOnlineCheck(userId);
                return true;
            }
            return false;
        }
    Replace it with:

    Code:
    public static boolean isOnline(int userId, String name) {
            int limboWorld = Limbo.get(userId);
            if (limboWorld != -1) {
                System.err.println(name + " is in limbo on world " + limboWorld + "!");
                return true;
            }
            for (World world : worlds) {
                if (!world.hasPlayer(name)) continue;
                System.err.println(name + " is online in world " + world.id + "!");
                world.sendOnlineCheck(name);
                return true;
            }
            return false;
        }
    Now go to io.ruin.central.model.world > World.java

    Add these 2 methods:

    Code:
        public Player get(String name) {
            for (Player player : this.players) {
                if (!player.name.equalsIgnoreCase(name)) continue;
                return player;
            }
            return null;
        }
    
        public boolean hasPlayer(String name) {
            return this.get(name) != null;
        }
    Now go to io.ruin.central.network > WorldSender.java

    Replace sendOnlineCheck method with this

    Code:
        public void sendOnlineCheck(String name) {
            OutBuffer out = new OutBuffer(5).sendFixedPacket(4).addString(name);
            this.write(out);
        }

    Now for changing player saving usernames instead of userids (You must do this):

    Go to io.ruin.central.model > Player.java

    Replace load, save, and getSaveFile methods with these:

    Code:
        public static String load(String username, World world) throws IOException {
            File file = Player.getSaveFile(username, world);
            return file.exists() ? new String(Files.readAllBytes(file.toPath())) : "";
        }
    
        public static boolean save(String username, World world, String json) {
            try {
                File file = Player.getSaveFile(username, world);
                Files.write(file.toPath(), json.getBytes(), new OpenOption[0]);
                return true;
            }
            catch (IOException e) {
                Server.logError(e.getMessage());
                return false;
            }
        }
    
        private static File getSaveFile(String username, World world) throws IOException {
            File folder = new File(System.getProperty("user.home") + "/Desktop/Kronos/_saved/players/" + world.stage.name().toLowerCase() + "/" + world.type.name().toLowerCase());
            if (!(folder.exists() || folder.mkdir() || folder.mkdirs())) {
                throw new IOException("Failed to make player saves folder for world: " + world.id + " (" + world.activity + ")");
            }
            return new File(System.getProperty("user.home") + "/Desktop/Kronos/_saved/players/" + world.stage.name().toLowerCase() + "/" + world.type.name().toLowerCase() + "/" + username + ".json");
        }
    Now go to io.ruin.central.network > WorldDecoder.java

    Find:

    Code:
    if (opcode == 3) {
    Replace that whole if statement with this:

    Code:
             if (opcode == 3) {
                int userId = in.readInt();
                int attempt = in.readUnsignedByte();
                String json = in.readString();
                Player player = Server.getPlayer(userId);
                if(player == null) {
                   return;
                }
                if (!Player.save(player.name, world, json)) {
                    return;
                }
                if (attempt != -1) {
                    world.sendSaveResponse(userId, attempt);
                }
                return;
            }
    Forums should now be fully removed and you can use the central server freely without any issues.

    Step Two: Fixing Friends and Clan Chat

    To save time we are just going to replace everything in these 7 class files:

    io.ruin.central.model.social > SocialList.java

    Code:
    package io.ruin.central.model.social;
    
    import com.google.gson.annotations.Expose;
    import io.ruin.api.utils.JsonUtils;
    import io.ruin.api.utils.StringUtils;
    import io.ruin.central.Server;
    import io.ruin.central.model.Player;
    import io.ruin.central.model.social.clan.ClanChat;
    import io.ruin.central.utility.XenUser;
    
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.OpenOption;
    import java.nio.file.StandardOpenOption;
    import java.util.HashMap;
    
    public class SocialList extends SocialContainer {
    
        public String username;
        private boolean sent;
           @ Expose public int privacy;
           @ Expose public ClanChat cc;
        private static final HashMap<String, SocialList> LOADED = new HashMap();
        private static final File social_folder = new File("_saved/social/");
    
        public static String capitalize(String s) {
            s = s.toLowerCase();
            s = s.replaceAll("_", " ");
            for (int i = 0; i < s.length(); i++) {
                if (i == 0) {
                    s = String.format("%s%s", Character.toUpperCase(s.charAt(0)), s.substring(1));
                }
                if (!Character.isLetterOrDigit(s.charAt(i))) {
                    if (i + 1 < s.length()) {
                        s = String.format("%s%s%s", s.subSequence(0, i+1), Character.toUpperCase(s.charAt(i + 1)), s.substring(i+2));
                    }
                }
            }
            return s;
        }
    
        public void offline(Player player) {
            this.sent = false;
            this.cc.leave(player, true);
            SocialList.save(this);
        }
    
        public void process(Player player) {
            if (!this.sent) {
                this.sent = true;
                this.update(null);
                player.sendSocial(true, this.friends);
                player.sendSocial(false, this.ignores);
                player.sendPrivacy(this.privacy);
                this.cc.init(player);
                return;
            }
            this.update(player);
        }
    
        private void update(Player sendFor) {
            if (this.friends != null) {
                for (SocialMember friend : this.friends) {
                    if (friend == null) continue;
                    int updatedWorldId = 0;
                    Player pFriend = Server.getPlayer(friend.name);
                    if (pFriend != null) {
                        boolean hidden;
                        friend.checkName(pFriend);
                        SocialList fList = SocialList.get(friend.name);
                        boolean bl = hidden = fList.privacy == 2 || fList.privacy == 1 && !fList.isFriend(this.username) || fList.isIgnored(this.username);
                        if (!hidden) {
                            updatedWorldId = pFriend.world.id;
                        }
                    }
                    if (friend.worldId == updatedWorldId && !friend.newName) continue;
                    friend.worldId = updatedWorldId;
                    if (sendFor == null) continue;
                    sendFor.sendSocial(true, friend);
                }
            }
            if (this.ignores != null) {
                for (SocialMember ignore : this.ignores) {
                    if (ignore == null) continue;
                    Player pIgnore = Server.getPlayer(ignore.name);
                    if (pIgnore != null) {
                        ignore.checkName(pIgnore);
                    }
                    if (ignore.worldId == 0 && !ignore.newName) continue;
                    ignore.worldId = 0;
                    if (sendFor == null) continue;
                    sendFor.sendSocial(false, ignore);
                }
            }
        }
    
        private void add(Player player, String name, boolean ignore) {
            name = capitalize(name);
            String type = ignore ? "ignore" : "friend";
           // XenUser.forObj(name, user -> {
                 /*       if (user == null) {
                            player.sendMessage("Unable to add " + type + " - social server offline.");
                            return;
                        }
                        if (user.name == null) {
                            player.sendMessage("Unable to add " + type + " - unknown player.");
                            return;
                        }*/
                        SocialMember member = new SocialMember(name, ignore ? null : SocialRank.FRIEND);
                        if (ignore) {
                            this.addIgnore(member);
                        } else if (this.addFriend(member) && this.cc.inClan(member.name)) {
                            this.cc.update(false);
                        }
                    //}
          //  );
        }
    
        private void delete(String name) {
            name = capitalize(name);
            String username = this.deleteFriend(name);
            if (!username.equals("") && this.cc.inClan(name)) {
                this.cc.update(false);
            }
        }
    
        public static void handle(Player player, String name, int requestType) {
            name = capitalize(name);
            if (requestType == 1) {
                player.socialList.add(player, name, false);
            } else if (requestType == 2) {
                player.socialList.delete(name);
            } else if (requestType == 3) {
                player.socialList.add(player, name, true);
            } else if (requestType == 4) {
                player.socialList.deleteIgnore(name);
            }
        }
    
        public static void sendPrivateMessage(Player player, int rankId, String name, String message) {
            Player receiver = Server.getPlayer(name);
            if (receiver == null) {
                return;
            }
            message = StringUtils.fixCaps(message);
            player.sendPM(name, message);
            receiver.sendReceivePM(player.name, rankId, message);
        }
    
        public static SocialList get(String username) {
            SocialList loaded = LOADED.get(username);
            if (loaded == null) {
                File file = new File(social_folder, username + ".json");
                if (file.exists()) {
                    try {
                        byte[] bytes = Files.readAllBytes(file.toPath());
                        String json = new String(bytes);
                        loaded = (SocialList) JsonUtils.GSON_EXPOSE.fromJson(json, SocialList.class);
                    } catch (Exception e) {
                        Server.logError(e.getMessage());
                    }
                }
                if (loaded == null) {
                    loaded = new SocialList();
                }
            }
            if (loaded.cc == null) {
                loaded.cc = new ClanChat();
            }
            loaded.cc.parent = loaded;
            loaded.username = username;
            LOADED.put(loaded.username, loaded);
            return loaded;
        }
    
        private static void save(SocialList list) {
            try {
                String json = JsonUtils.GSON_EXPOSE.toJson(list);
                if(!social_folder.exists() && !social_folder.mkdirs())
                    throw new IOException("social directory could not be created!");
                Files.write(new File(social_folder, list.username + ".json").toPath(), json.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
            } catch (Exception e) {
                Server.logError(e.getMessage());
            }
        }
    }
    io.ruin.central.model.social.clan > ClanContainer.java

    Code:
    package io.ruin.central.model.social.clan;
    
    import io.ruin.central.model.social.SocialMember;
    
    public class ClanContainer {
        public int ccMembersCount;
        public SocialMember[] ccMembers;
    
        public boolean addClanMember(SocialMember member) {
            if (this.ccMembers == null) {
                this.ccMembers = new SocialMember[100];
            }
            if (this.ccMembersCount >= this.ccMembers.length || this.inClan(member.name)) {
                return false;
            }
            this.ccMembers[this.ccMembersCount++] = member;
            return true;
        }
    
        public void removeClanMember(String name) {
            for (int index = 0; index < this.ccMembersCount; ++index) {
                SocialMember member = this.ccMembers[index];
                if (!name.equalsIgnoreCase(member.name)) continue;
                --this.ccMembersCount;
                for (int i = index; i < this.ccMembersCount; ++i) {
                    this.ccMembers[i] = this.ccMembers[i + 1];
                }
                this.ccMembers[this.ccMembersCount] = null;
                return;
            }
        }
    
        public SocialMember getClanMember(String username) {
            if (this.ccMembers == null) {
                return null;
            }
            for (SocialMember member : this.ccMembers) {
                if (member == null || !member.name.equalsIgnoreCase(username)) continue;
                return member;
            }
            return null;
        }
    
        public boolean inClan(String name) {
            return this.getClanMember(name) != null;
        }
    }
    io.ruin.central.model > Player.java

    Code:
    package io.ruin.central.model;
    
    import io.ruin.api.buffer.OutBuffer;
    import io.ruin.api.filestore.utility.Huffman;
    import io.ruin.api.protocol.Protocol;
    import io.ruin.api.utils.FileUtils;
    import io.ruin.api.utils.Random;
    import io.ruin.central.Server;
    import io.ruin.central.model.social.SocialList;
    import io.ruin.central.model.social.SocialMember;
    import io.ruin.central.model.social.clan.ClanChat;
    import io.ruin.central.model.world.World;
    
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.OpenOption;
    import java.util.List;
    
    public class Player {
    
        public final int userId;
        public final String name;
        public final World world;
        public final boolean admin;
        public final SocialList socialList;
    
        public Player(int userId, String name, List<Integer> groupIds, World world) {
            this.userId = userId;
            this.name = name;
            this.admin = groupIds.contains(3);
            this.world = world;
            this.socialList = SocialList.get(name);
        }
    
        public ClanChat getClanChat() {
            return this.socialList.cc;
        }
    
        public ClanChat getActiveClanChat() {
            return this.socialList.cc.active;
        }
    
        public void destroy() {
            this.socialList.offline(this);
        }
    
        public void process() {
            this.socialList.process(this);
        }
    
        public void write(OutBuffer out) {
            out.encode(null);
            this.world.sendClientPacket(this.userId, out.toByteArray());
        }
    
        public void sendMessage(String message) {
            this.sendMessage(message, 0);
        }
    
        public void sendMessage(String message, int type) {
            this.write(Protocol.messagePacket(message, null, type));
        }
    
        public void sendPrivacy(int privacy) {
            OutBuffer out = new OutBuffer(2).sendFixedPacket(17).addByte(privacy);
            this.write(out);
        }
    
        public void sendSocial(boolean friendType, SocialMember... list) {
            if (friendType) {
                this.sendFriends(list);
            } else {
                this.sendIgnores(list);
            }
        }
    
        private void sendFriends(SocialMember ... friends) {
            OutBuffer out = new OutBuffer(friends == null ? 3 : 255).sendVarShortPacket(61);
            if (friends != null) {
                for (SocialMember friend : friends) {
                    if (friend == null) continue;
                    out.addByte(friend.sendNewName() ? 1 : 0);
                    out.addString(friend.name);
                    out.addString(friend.lastName);
                    out.addShort(friend.worldId);
                    out.addByte(friend.rank == null ? -1 : friend.rank.id);
                    out.addByte(0);
                    if (friend.worldId > 0) {
                        out.skip(6);
                    }
                    out.skip(1);
                }
            }
            this.write(out);
        }
    
        private void sendIgnores(SocialMember ... ignores) {
            OutBuffer out = new OutBuffer(255).sendVarShortPacket(59);
            if (ignores != null) {
                for (SocialMember ignore : ignores) {
                    if (ignore == null) continue;
                    out.addByte(ignore.sendNewName() ? 1 : 0);
                    out.addString(ignore.name);
                    out.addString(ignore.lastName);
                    out.skip(1);
                }
            }
           this.write(out);
        }
    
        public void sendPM(String toUsername, String message) {
            this.write(Protocol.outgoingPm(toUsername, message));
        }
    
        public void sendReceivePM(String fromName, int fromRank, String message) {
            OutBuffer out = new OutBuffer(255).sendVarShortPacket(45)
                    .addString(fromName);
            for (int i = 0; i < 5; ++i) {
                out.addByte(Random.get(255));
            }
            out.addByte(fromRank);
            Huffman.encrypt(out, message);
           this.write(out);
        }
    
        public static String load(String username, World world) throws IOException {
            File file = Player.getSaveFile(username, world);
            return file.exists() ? new String(Files.readAllBytes(file.toPath())) : "";
        }
    
        public static boolean save(String username, World world, String json) {
            try {
                File file = Player.getSaveFile(username, world);
                Files.write(file.toPath(), json.getBytes(), new OpenOption[0]);
                return true;
            }
            catch (IOException e) {
                Server.logError(e.getMessage());
                return false;
            }
        }
    
        private static File getSaveFile(String username, World world) throws IOException {
            File folder = new File(System.getProperty("user.home") + "/Desktop/Kronos/_saved/players/" + world.stage.name().toLowerCase() + "/" + world.type.name().toLowerCase());
            if (!(folder.exists() || folder.mkdir() || folder.mkdirs())) {
                throw new IOException("Failed to make player saves folder for world: " + world.id + " (" + world.activity + ")");
            }
            return new File(System.getProperty("user.home") + "/Desktop/Kronos/_saved/players/" + world.stage.name().toLowerCase() + "/" + world.type.name().toLowerCase() + "/" + username + ".json");
        }
    }
    io.ruin.central.model.social > SocialContainer.java

    Code:
    package io.ruin.central.model.social;
    
    import com.google.gson.annotations.Expose;
    
    public class SocialContainer {
    
           @ Expose protected int friendsCount;
           @ Expose public SocialMember[] friends;
           @ Expose protected int ignoresCount;
           @ Expose public SocialMember[] ignores;
    
        public boolean addFriend(SocialMember friend) {
            if (this.friends == null) {
                this.friends = new SocialMember[400];
            }
            if (this.friendsCount >= this.friends.length || this.isFriend(friend.name)) {
                return false;
            }
            this.friends[this.friendsCount++] = friend;
            return true;
        }
    
        public String deleteFriend(String name) {
            for (int index = 0; index < this.friendsCount; ++index) {
                SocialMember friend = this.friends[index];
                if (!name.equalsIgnoreCase(friend.name)) continue;
                --this.friendsCount;
                for (int i = index; i < this.friendsCount; ++i) {
                    this.friends[i] = this.friends[i + 1];
                }
                this.friends[this.friendsCount] = null;
                return friend.name;
            }
            return "";
        }
    
        public SocialMember getFriend(String name) {
            if (this.friends == null) {
                return null;
            }
            for (SocialMember friend : this.friends) {
                if (friend == null || !friend.name.equalsIgnoreCase(name)) continue;
                return friend;
            }
            return null;
        }
    
        public boolean isFriend(String name) {
            return this.getFriend(name) != null;
        }
    
        public void addIgnore(SocialMember ignore) {
            if (this.ignores == null) {
                this.ignores = new SocialMember[400];
            }
            if (this.ignoresCount >= this.ignores.length || this.isIgnored(ignore.name)) {
                return;
            }
            this.ignores[this.ignoresCount++] = ignore;
        }
    
        public String deleteIgnore(String name) {
            for (int index = 0; index < this.ignoresCount; ++index) {
                SocialMember ignore = this.ignores[index];
                if (!name.equalsIgnoreCase(ignore.name)) continue;
                --this.ignoresCount;
                for (int i = index; i < this.ignoresCount; ++i) {
                    this.ignores[i] = this.ignores[i + 1];
                }
                this.ignores[this.ignoresCount] = null;
                return ignore.name;
            }
            return "";
        }
    
        public SocialMember getIgnore(String username) {
            if (this.ignores == null) {
                return null;
            }
            for (SocialMember ignore : this.ignores) {
                if (ignore == null || !username.equalsIgnoreCase(ignore.name)) continue;
                return ignore;
            }
            return null;
        }
    
        public boolean isIgnored(String username) {
            return this.getIgnore(username) != null;
        }
    }
    io.ruin.central.model.social.clan > ClanChat.java

    Code:
    package io.ruin.central.model.social.clan;
    
    import com.google.gson.annotations.Expose;
    import io.ruin.api.buffer.OutBuffer;
    import io.ruin.api.filestore.utility.Huffman;
    import io.ruin.api.utils.Random;
    import io.ruin.api.utils.StringUtils;
    import io.ruin.central.Server;
    import io.ruin.central.model.Player;
    import io.ruin.central.model.social.SocialList;
    import io.ruin.central.model.social.SocialMember;
    import io.ruin.central.model.social.SocialRank;
    import io.ruin.central.utility.XenUser;
    
    import java.util.HashMap;
    
    public class ClanChat extends ClanContainer {
    
        public SocialList parent;
        private String owner;
           @ Expose private String lastName = "";
           @ Expose public String name;
           @ Expose public SocialRank enterRank = null;
           @ Expose public SocialRank talkRank = null;
           @ Expose public SocialRank kickRank = SocialRank.CORPORAL;
        public ClanChat active;
        private boolean joining;
        private HashMap<Integer, Long> kicked;
    
        public void init(Player player) {
            this.sendSettings(player);
            if (!this.lastName.equals("")) {
                this.join(player, this.lastName);
            }
        }
    
        private void sendSettings(Player player) {
            String name = this.name == null ? "Chat disabled" : this.name;
            int enterRank = this.enterRank == null ? -1 : this.enterRank.id;
            int talkRank = this.talkRank == null ? -1 : this.talkRank.id;
            int kickRank = this.kickRank.id;
            OutBuffer out = new OutBuffer(2 + (name.length() + 1) + 3).sendVarBytePacket(86).addString(name).addByte(enterRank).addByte(talkRank).addByte(kickRank);
            player.write(out);
        }
    
        public void update(boolean settingsOnly) {
            if (this.ccMembersCount == 0) {
                return;
            }
            OutBuffer out = settingsOnly ? this.getSettingsBuffer() : this.getChannelBuffer();
            for (int i = 0; i < this.ccMembersCount; ++i) {
                SocialMember member = this.ccMembers[i];
                Player pMember = Server.getPlayer(member.name);
                if (pMember == null) continue;
                pMember.write(out);
            }
        }
    
        public void disable() {
            for (int i = 0; i < this.ccMembersCount; ++i) {
                SocialMember member = this.ccMembers[i];
                Player pMember = Server.getPlayer(member.name);
                if (pMember == null) continue;
                pMember.getClanChat().setActive(pMember, null);
                pMember.sendMessage("The clan chat channel you were in has been disabled.", 11);
            }
            if (this.kicked != null) {
                this.kicked.clear();
                this.kicked = null;
            }
        }
    
        public boolean isDisabled() {
            return this.name == null;
        }
    
        private void setActive(Player player, ClanChat newActive) {
            if (this.active == newActive) {
                return;
            }
            if (newActive == null) {
                this.active.removeClanMember(player.name);
                player.write(this.active.getLeaveBuffer());
                if (!this.active.isDisabled()) {
                    this.active.update(false);
                }
            } else {
                this.lastName = newActive.parent.username;
                newActive.update(false);
            }
            this.active = newActive;
        }
    
        public static String capitalize(String s) {
            s = s.toLowerCase();
            s = s.replaceAll("_", " ");
            for (int i = 0; i < s.length(); i++) {
                if (i == 0) {
                    s = String.format("%s%s", Character.toUpperCase(s.charAt(0)), s.substring(1));
                }
                if (!Character.isLetterOrDigit(s.charAt(i))) {
                    if (i + 1 < s.length()) {
                        s = String.format("%s%s%s", s.subSequence(0, i+1), Character.toUpperCase(s.charAt(i + 1)), s.substring(i+2));
                    }
                }
            }
            return s;
        }
    
    
        public void join(Player player, String name) {
            name = capitalize(name);
          /*  if (user == null) {
                player.sendMessage("Unable to join channel - social server offline.", 11);
                return;
            }
            if (user.name == null) {
                player.sendMessage("The channel you tried to join does not exist.", 11);
                return;
            }*/
            if (this.active != null) {
                player.sendMessage("You are already in a channel!", 11);
                return;
            }
            SocialList ownerList = SocialList.get(name);
            if (ownerList.isIgnored(player.name)) {
                player.sendMessage("You are blocked from joining this channel.");
                return;
            }
            ClanChat joinCc = ownerList.cc;
            joinCc.owner = name;
            if (joinCc.addMember(player)) {
                this.setActive(player, joinCc);
                player.sendMessage("Now talking in clan chat channel " + joinCc.name + ".", 11);
                player.sendMessage("To talk, start each line of chat with the / symbol.", 11);
            }
        }
    
        public void leave(Player player, boolean logout) {
            if (this.active == null) {
                return;
            }
            this.lastName = logout ? this.active.parent.username : "";
            this.setActive(player, null);
        }
    
        public void kick(Player kickedBy, String kickName) {
            if (this.isDisabled()) {
                return;
            }
            SocialRank kickerRank = this.getRank(kickedBy);
            if (!ClanChat.meetsRank(this.kickRank, kickerRank)) {
                kickedBy.sendMessage("You are not a high enough rank to kick from this channel.", 11);
                return;
            }
            Player toKick = Server.getPlayer(kickName);
            if (toKick == null || toKick.getActiveClanChat() != this) {
                kickedBy.sendMessage(kickName + " is not active in this channel.", 11);
                return;
            }
            SocialRank toKickRank = this.getRank(toKick);
            if (toKickRank == SocialRank.OWNER) {
                kickedBy.sendMessage("You can't kick this channel's owner!", 11);
                return;
            }
            if (!ClanChat.meetsRank(toKickRank, kickerRank)) {
                kickedBy.sendMessage("You are not a high enough rank to kick this member.", 11);
                return;
            }
            if (this.kicked == null) {
                this.kicked = new HashMap();
            }
            this.kicked.put(toKick.userId, System.currentTimeMillis() + 3600000L);
            toKick.getClanChat().leave(toKick, false);
            toKick.sendMessage("You have been kicked from the channel.", 11);
        }
    
        private boolean addMember(Player pMember) {
            Long kickedUntil;
            if (this.isDisabled()) {
                pMember.sendMessage("The channel you tried to join is currently disabled.", 11);
                return false;
            }
            if (this.kicked != null && (kickedUntil = this.kicked.get(pMember.userId)) != null) {
                if (kickedUntil > System.currentTimeMillis()) {
                    pMember.sendMessage("You cannot join this channel because you are currently banned from it.", 11);
                    return false;
                }
                this.kicked.remove(pMember.userId);
            }
            if (!ClanChat.meetsRank(this.enterRank, this.getRank(pMember))) {
                pMember.sendMessage("You are not a high enough rank to enter this channel.", 11);
                return false;
            }
            if (!this.addClanMember(new SocialMember(pMember.userId, pMember.name, pMember.world.id))) {
                pMember.sendMessage("The channel you tried to join is full.", 11);
                return false;
            }
            return true;
        }
    
        public void message(Player sender, int rankId, String message) {
            if (this.isDisabled()) {
                return;
            }
            SocialRank senderRank = this.getRank(sender);
            if (!ClanChat.meetsRank(this.talkRank, senderRank)) {
                sender.sendMessage("You are not a high enough rank to talk in this channel.", 11);
                return;
            }
            message = StringUtils.fixCaps(message);
            for (int i = 0; i < this.ccMembersCount; ++i) {
                SocialMember member = this.ccMembers[i];
                Player pMember = Server.getPlayer(member.name);
                if (pMember == null) continue;
                pMember.write(this.getMessageBuffer(sender.name, rankId, message));
            }
        }
    
        private OutBuffer getMessageBuffer(String senderName, int rankId, String message) {
            OutBuffer out = new OutBuffer(255).sendVarBytePacket(22);
            out.addString(senderName);
            out.addString(this.name);
            for (int i = 0; i < 5; ++i) {
                out.addByte(Random.get(255));
            }
            out.addByte(rankId);
            Huffman.encrypt(out, message);
            return out;
        }
    
        private OutBuffer getBuffer(int type) {
            if (type == 0) {
                return new OutBuffer(3).sendVarShortPacket(48);
            }
            OutBuffer out = new OutBuffer(255).sendVarShortPacket(48).
                    addString(this.owner).
                    addString(this.name).
                    addByte(ClanChat.getRankId(this.kickRank));
            if (type == 2) {
                out.addByte(255);
                return out;
            }
            out.addByte(this.ccMembersCount);
            for (int i = 0; i < this.ccMembersCount; ++i) {
                SocialMember member = this.ccMembers[i];
                out.addString(member.name);
                out.addShort(member.worldId);
                out.addByte(this.getRankId(member.name));
                out.addByte(0);
            }
            return out;
        }
    
        private OutBuffer getLeaveBuffer() {
            return this.getBuffer(0);
        }
    
        private OutBuffer getChannelBuffer() {
            return this.getBuffer(1);
        }
    
        private OutBuffer getSettingsBuffer() {
            return this.getBuffer(2);
        }
    
        private SocialRank getRank(Player player) {
            if (player.name.equalsIgnoreCase(this.parent.username)) {
                return SocialRank.OWNER;
            }
            if (player.admin) {
                return SocialRank.ADMIN;
            }
            SocialMember friend = this.parent.getFriend(player.name);
            return friend == null ? null : friend.rank;
        }
    
        private int getRankId(String username) {
            if (username.equalsIgnoreCase(this.parent.username)) {
                return SocialRank.OWNER.id;
            }
            Player player = Server.getPlayer(username);
            if (player != null && player.admin) {
                return SocialRank.ADMIN.id;
            }
            SocialMember friend = this.parent.getFriend(player.name);
            return friend == null ? -1 : friend.rank.id;
        }
    
        private static int getRankId(SocialRank rank) {
            return rank == null ? -1 : rank.id;
        }
    
        private static boolean meetsRank(SocialRank reqRank, SocialRank checkRank) {
            return reqRank == null || checkRank != null && checkRank.id >= reqRank.id;
        }
    }
    io.ruin.central.network > WorldDecoder.java

    Code:
    package io.ruin.central.network;
    
    import io.ruin.api.buffer.InBuffer;
    import io.ruin.api.netty.MessageDecoder;
    import io.ruin.api.protocol.login.LoginInfo;
    import io.ruin.api.utils.IPBans;
    import io.ruin.api.utils.MACBan;
    import io.ruin.api.utils.UUIDBan;
    import io.ruin.central.Server;
    import io.ruin.central.model.Player;
    import io.ruin.central.model.social.SocialList;
    import io.ruin.central.model.social.SocialMember;
    import io.ruin.central.model.social.SocialRank;
    import io.ruin.central.model.social.clan.ClanChat;
    import io.ruin.central.model.world.World;
    import io.ruin.central.model.world.WorldLogin;
    
    public class WorldDecoder extends MessageDecoder<World> {
        public long lastMessageAt = System.currentTimeMillis();
    
        public WorldDecoder() {
            super(null, true);
        }
    
        @Override
        public void handle(World world, InBuffer in, int opcode) {
            this.lastMessageAt = System.currentTimeMillis();
            if (opcode == 0) {
                return;
            }
            if (opcode == 1) {
                String ip = in.readString();
                String name = in.readString();
                String password = in.readString();
                String email = in.readString();
                String macAddress = in.readString();
                String uuid = in.readString();
                int tfaCode = in.readMedium();
                boolean tfaTrust = in.readByte() == 1;
                int tfaTrustKey = in.readUnsignedByte();
                new WorldLogin(world, new LoginInfo(ip, name, password, email, macAddress, uuid, tfaCode, tfaTrust, tfaTrustKey));
                return;
            }
            if (opcode == 2) {
                int userId = in.readInt();
                world.removePlayer(userId);
                return;
            }
            if (opcode == 3) {
                int userId = in.readInt();
                int attempt = in.readUnsignedByte();
                String json = in.readString();
                Player player = Server.getPlayer(userId);
                if(player == null) {
                   return;
                }
                if (!Player.save(player.name, world, json)) {
                    return;
                }
                if (attempt != -1) {
                    world.sendSaveResponse(userId, attempt);
                }
                return;
            }
            if (opcode == 4) {
                int userId = in.readInt();
                String message = in.readString();
                if (userId == -1) {
                    for (World w : Server.worlds) {
                        for (Player p : w.players) {
                            p.sendMessage(message);
                        }
                    }
                } else {
                    Player player = Server.getPlayer(userId);
                    if (player == null) {
                        return;
                    }
                    player.sendMessage(message);
                    for (World w : Server.worlds) {
                        for (Player p : w.players) {
                            if (!p.socialList.isFriend(player.name)) continue;
                            p.sendMessage(message);
                        }
                    }
                }
                return;
            }
            if (opcode == 5) {
                int userId = in.readInt();
                byte privacy = in.readByte();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                player.socialList.privacy = privacy;
                return;
            }
            if (opcode == 6) {
                int userId = in.readInt();
                String username = in.readString();
                byte requestType = in.readByte();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                SocialList.handle(player, username, requestType);
                return;
            }
            if (opcode == 7) {
                int senderId = in.readInt();
                byte rankId = in.readByte();
                String username = in.readString();
                String message = in.readString();
                Player sender = Server.getPlayer(senderId);
                if (sender == null) {
                    return;
                }
                SocialList.sendPrivateMessage(sender, rankId, username, message);
                return;
            }
            if (opcode == 8) {
                int userId = in.readInt();
                String name = in.readString();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                ClanChat cc = player.getClanChat();
                if (name.isEmpty()) {
                    cc.name = null;
                    cc.disable();
                } else {
                    cc.name = name;
                    cc.update(true);
                }
                return;
            }
            if (opcode == 9) {
                int userId = in.readInt();
                byte settingId = in.readByte();
                byte value = in.readByte();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                ClanChat cc = player.getClanChat();
                if (settingId == 0) {
                    cc.enterRank = SocialRank.get(value, null);
                } else if (settingId == 1) {
                    cc.talkRank = SocialRank.get(value, null);
                } else {
                    cc.kickRank = SocialRank.get(value, SocialRank.CORPORAL);
                    cc.update(true);
                }
                return;
            }
            if (opcode == 10) {
                int userId = in.readInt();
                String friendName = in.readString();
                SocialRank rank = SocialRank.get(in.readByte(), null);
                if (rank == null) {
                    return;
                }
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                SocialMember friend = player.socialList.getFriend(friendName);
                if (friend == null || friend.rank == rank) {
                    return;
                }
                friend.rank = rank;
                friend.resend();
                ClanChat cc = player.getClanChat();
                if (cc.inClan(friend.name)) {
                    cc.update(false);
                }
                return;
            }
            if (opcode == 11) {
                int userId = in.readInt();
                String ownerName = in.readString();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                if (ownerName.isEmpty()) {
                    player.getClanChat().leave(player, false);
                } else {
                    player.getClanChat().join(player, ownerName);
                }
                return;
            }
            if (opcode == 12) {
                int userId = in.readInt();
                String kickName = in.readString();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                ClanChat active = player.getActiveClanChat();
                if (active == null) {
                    return;
                }
                active.kick(player, kickName);
                return;
            }
            if (opcode == 13) {
                int userId = in.readInt();
                byte rankId = in.readByte();
                String message = in.readString();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                ClanChat active = player.getActiveClanChat();
                if (active == null) {
                    return;
                }
                active.message(player, rankId, message);
                return;
            }
            if (opcode == 14) {
                IPBans.refreshBans();
                MACBan.refreshBans();
                UUIDBan.refreshBans();
                return;
            }
            if (opcode == 15) {
                String uuid = in.readString();
                UUIDBan.requestBan(uuid);
                return;
            }
            if (opcode == 16) {
                String ip = in.readString();
                int userId = in.readInt();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                IPBans.requestBan(player.name, ip);
                return;
            }
            if (opcode == 17) {
                String mac = in.readString();
                int userId = in.readInt();
                Player player = Server.getPlayer(userId);
                if (player == null) {
                    return;
                }
                MACBan.requestBan(player.name, mac);
                return;
            }
        }
    
        @Override
        public int getSize(int opcode) {
            switch (opcode) {
                case 0:
                case 14: {
                    return 0;
                }
                case 1: {
                    return -1;
                }
                case 2: {
                    return 4;
                }
                case 3: {
                    return -4;
                }
                case 4: {
                    return -1;
                }
                case 5: {
                    return 5;
                }
                case 6: {
                    return -1;
                }
                case 7: {
                    return -1;
                }
                case 8: {
                    return -1;
                }
                case 9: {
                    return 6;
                }
                case 10: {
                    return -1;
                }
                case 11: {
                    return -1;
                }
                case 12: {
                    return -1;
                }
                case 13: {
                    return -1;
                }
                case 15: {
                    return -1;
                }
                case 16: {
                    return -1;
                }
                case 17: {
                    return -1;
                }
            }
            return -128;
        }
    }
    io.ruin.central.model.social > SocialMember.java

    Code:
    package io.ruin.central.model.social;
    
    import com.google.gson.annotations.Expose;
    import io.ruin.central.model.Player;
    import io.ruin.central.utility.XenUser;
    
    import java.util.Objects;
    
    public class SocialMember {
    
           @ Expose public String name;
           @ Expose public String lastName;
        protected boolean newName;
           @ Expose public SocialRank rank;
        public int worldId = -1;
    
        public SocialMember(XenUser user, SocialRank rank) {
            this.name = user.name;
            this.lastName = (user.lastName == null || user.lastName.equalsIgnoreCase("null")) ? "" : user.lastName;
            this.rank = rank;
        }
    
        public SocialMember(String username, SocialRank rank) {
            this.name = username;
            this.lastName = "";
            this.rank = rank;
        }
    
    
        public SocialMember(int userId, String name, int worldId) {
            this.name = name;
            this.lastName = "";
            this.worldId = worldId;
        }
    
        public void resend() {
            this.worldId = -1;
        }
    
        protected void checkName(Player player) {
            if (!Objects.equals(this.name, player.name)) {
                System.err.print(this.name);
                this.lastName = this.name;
                this.name = player.name;
                this.newName = true;
            }
        }
    
        public boolean sendNewName() {
            if (this.newName) {
                this.newName = false;
                this.resend();
                return true;
            }
            return false;
        }
    }
    And that's all you need to do for Friends and Clan chat to work.

    Step Three: Password Saving (Do This AFTER Friends and Clan Chat fix to avoid bugs/errors)

    Go to io.ruin.model.entity.player > PlayerLogin.java

    Find:

    Code:
            if (player == null) {
                    deny(Response.ERROR_LOADING_ACCOUNT);
                    return;
                }
    Right below that add:

    Code:
                if(player.getPassword() != null) {
                    if (!info.password.equalsIgnoreCase(player.getPassword())) {
                        deny(Response.INVALID_LOGIN);
                        return;
                    }
                }
    Now go to io.ruin.model.entity.player > Player.java

    Find

    Code:
        private String password;
    Change it to

    Code:
        @ Expose private String password;
    Your accounts will now be password protected

    If you ever get this error, ignore it, it won't impact anything:

    Code:
    [ForkJoinPool.commonPool-worker-2] ERROR rollingErrorFileLogger - Failed to post: https://community.kronos.rip/integration/index.php
    java.io.IOException: Server returned HTTP response code: 522 for URL: https://community.kronos.rip/integration/index.php
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1900)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:268)
        at io.ruin.api.utils.PostWorker.post(PostWorker.java:65)
        at io.ruin.api.utils.PostWorker.postArray(PostWorker.java:82)
        at io.ruin.api.utils.XenPost.post(XenPost.java:15)
        at io.ruin.model.entity.player.PlayerGroup.lambda$sync$0(PlayerGroup.java:72)
        at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1640)
        at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1632)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
    Please post any bugs/errors and I will fix them.
    Reply With Quote  
     


  2. #2  
    Gauntlet Founder
    bowlcutgod's Avatar
    Join Date
    Mar 2020
    Posts
    62
    Thanks given
    2
    Thanks received
    8
    Rep Power
    32
    Amazing work my friend! thanks for sharing all those snippets
    Reply With Quote  
     

  3. Thankful user:


  4. #3  
    Extreme Donator [Kronos] Removing Forum Login, Fixing Friends Chat and Clan Chat, Password Saving Market Banned



    Join Date
    Dec 2010
    Age
    25
    Posts
    6,060
    Thanks given
    1,692
    Thanks received
    1,238
    Rep Power
    1765
    Thanks for this. Will be useful for others.
    Reply With Quote  
     

  5. Thankful user:


  6. #4  
    ♫ Musical Project ♫

    Natalie's Avatar
    Join Date
    Dec 2015
    Posts
    172
    Thanks given
    91
    Thanks received
    59
    Rep Power
    154
    Quote Originally Posted by Armo View Post
    Please post any bugs/errors and I will fix them.
    I've followed the tutorial, and noticed a bug with the clan chat. If you make a clan channel, and join that it'll work fine. But once you logout, turn off the servers and back on, then re-login again it will say "you're already in a channel", but you're not in a channel when you login..

    Also, this snippet may need to be updated now for the new changes that was made from this. https://www.rune-server.ee/runescape...nk-groups.html Since, we're not using OfflineMode, anymore.
    Last edited by Natalie; 02-22-2021 at 08:48 AM.
    Reply With Quote  
     

  7. #5  
    Phoenix owner

    Join Date
    Feb 2019
    Posts
    55
    Thanks given
    0
    Thanks received
    7
    Rep Power
    16
    Can you make thread how to switch to ips forum?
    Reply With Quote  
     

  8. #6  
    RuneCasino


    Join Date
    Jul 2007
    Posts
    1,647
    Thanks given
    175
    Thanks received
    257
    Rep Power
    358
    Quote Originally Posted by Natalynn View Post
    I've followed the tutorial, and noticed a bug with the clan chat. If you make a clan channel, and join that it'll work fine. But once you logout, turn off the servers and back on, then re-login again it will say "you're already in a channel", but you're not in a channel when you login..

    Also, this snippet may need to be updated now for the new changes that was made from this. https://www.rune-server.ee/runescape...nk-groups.html Since, we're not using OfflineMode, anymore.

    I'll fix both problems soon
    Reply With Quote  
     

  9. #7  
    Registered Member
    Join Date
    Feb 2021
    Posts
    38
    Thanks given
    16
    Thanks received
    6
    Rep Power
    4
    Quote Originally Posted by Armo View Post
    Do not use the old thread I made about removing forum login and UNDO any changes that you made.
    It is recommended that you re-download Kronos if you used that tutorial.
    Which old one? I followed all ur tutorials/snippets, I can't undo now, and I cannot re-download the server again after I putted a lot of work, so can u please explain what excatly I should UNDO? And which tut it is ?
    Reply With Quote  
     

  10. #8  
    RuneCasino


    Join Date
    Jul 2007
    Posts
    1,647
    Thanks given
    175
    Thanks received
    257
    Rep Power
    358
    Quote Originally Posted by OSRS. View Post
    Which old one? I followed all ur tutorials/snippets, I can't undo now, and I cannot re-download the server again after I putted a lot of work, so can u please explain what excatly I should UNDO? And which tut it is ?
    It was deleted, it involved changing lots of things to remove forum login but it was done wrong. If you follow this tutorial and come across any errors I will assist you.
    Reply With Quote  
     

  11. Thankful user:


  12. #9  
    Registered Member
    Join Date
    Feb 2021
    Posts
    38
    Thanks given
    16
    Thanks received
    6
    Rep Power
    4
    Quote Originally Posted by Armo View Post
    It was deleted, it involved changing lots of things to remove forum login but it was done wrong. If you follow this tutorial and come across any errors I will assist you.
    I followed everything u posted here, and have no errors, but i'm afraid if still getting bugs from ur old thread bro, also the clan chat still doesn't work and the pms still showing me "Loading friends/Ignore list.. Please wait"
    Reply With Quote  
     

  13. #10  
    Extreme Donator


    Join Date
    Jul 2008
    Age
    31
    Posts
    956
    Thanks given
    186
    Thanks received
    344
    Rep Power
    1060
    Good job with this. Thanks for contributing.
    Reply With Quote  
     

Page 1 of 2 12 LastLast

Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)


User Tag List

Similar Threads

  1. Friends Chat and Clan Chat
    By Nickhagro in forum Help
    Replies: 1
    Last Post: 08-20-2015, 08:27 PM
  2. Friend list and friend chat sprite
    By Coontown in forum Requests
    Replies: 6
    Last Post: 08-10-2011, 05:44 AM
  3. rs clan chat and friend chat sprites
    By Gladius. in forum Requests
    Replies: 2
    Last Post: 06-22-2011, 09:39 AM
  4. Replies: 0
    Last Post: 03-04-2010, 04:48 AM
  5. Replies: 0
    Last Post: 03-04-2010, 03:14 AM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •