diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt
index d9b90d73b843d64ab41a9da69fb23b73ffcf18ab..60c584f2cbffde72d87aa242289b61482b7623b9 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/viewmodel/QuasselViewModel.kt
@@ -25,7 +25,6 @@ import de.kuschku.quasseldroid_ng.util.helper.switchMap
 import de.kuschku.quasseldroid_ng.util.helper.switchMapRx
 import de.kuschku.quasseldroid_ng.util.helper.zip
 import io.reactivex.Observable
-import io.reactivex.functions.BiFunction
 import io.reactivex.functions.Function
 import java.util.concurrent.TimeUnit
 
@@ -102,7 +101,7 @@ class QuasselViewModel : ViewModel() {
           when (info.type.toInt()) {
             BufferInfo.Type.QueryBuffer.toInt()   -> {
               network.liveIrcUser(info.bufferName).switchMap { user ->
-                user.live_realName.map { realName ->
+                user.liveRealName().map { realName ->
                   ToolbarFragment.BufferData(
                     info = info,
                     network = network.networkInfo(),
@@ -115,7 +114,7 @@ class QuasselViewModel : ViewModel() {
               network.liveIrcChannel(
                 info.bufferName
               ).switchMap { channel ->
-                channel.live_topic.map { topic ->
+                channel.liveTopic().map { topic ->
                   ToolbarFragment.BufferData(
                     info = info,
                     network = network.networkInfo(),
@@ -145,39 +144,46 @@ class QuasselViewModel : ViewModel() {
     }
   }
 
-  val nickData = session.zip(buffer).switchMapRx { (session, buffer) ->
+  val nickData: LiveData<List<NickListAdapter.IrcUserItem>?> = session.zip(
+    buffer
+  ).switchMapRx { (session, buffer) ->
     val bufferSyncer = session?.bufferSyncer
     val bufferInfo = bufferSyncer?.bufferInfo(buffer)
     if (bufferInfo?.type?.hasFlag(Buffer_Type.ChannelBuffer) == true) {
       val network = session.networks[bufferInfo.networkId]
       val ircChannel = network?.ircChannel(bufferInfo.bufferName)
       if (ircChannel != null) {
-        Observable.combineLatest(
-          ircChannel.ircUsers().map { user ->
-            Observable.zip(
-              user.live_realName, user.live_away,
-              BiFunction<String, Boolean, Pair<String, Boolean>> { a, b -> Pair(a, b) }
-            ).map { (realName, away) ->
-              val userModes = ircChannel.userModes(user)
-              val prefixModes = network.prefixModes()
+        ircChannel.liveIrcUsers().switchMap { users ->
+          Observable.combineLatest(
+            users.map<IrcUser, Observable<NickListAdapter.IrcUserItem>?> { user ->
+              user.liveNick().switchMap { nick ->
+                user.liveRealName().switchMap { realName ->
+                  user.liveIsAway().map { away ->
+                    val userModes = ircChannel.userModes(user)
+                    val prefixModes = network.prefixModes()
 
-              val lowestMode = userModes.mapNotNull {
-                prefixModes.indexOf(it)
-              }.min() ?: prefixModes.size
+                    val lowestMode = userModes.mapNotNull {
+                      prefixModes.indexOf(it)
+                    }.min() ?: prefixModes.size
 
-              NickListAdapter.IrcUserItem(
-                user.nick(),
-                network.modesToPrefixes(userModes),
-                lowestMode,
-                realName,
-                away,
-                network.support("CASEMAPPING")
-              )
+                    NickListAdapter.IrcUserItem(
+                      nick,
+                      network.modesToPrefixes(userModes),
+                      lowestMode,
+                      realName,
+                      away,
+                      network.support("CASEMAPPING")
+                    )
+                  }
+                }
+              }
+            },
+            object : Function<Array<Any>, List<NickListAdapter.IrcUserItem>> {
+              override fun apply(array: Array<Any>) =
+                array.toList() as List<NickListAdapter.IrcUserItem>
             }
-          }, { array: Array<Any> ->
-            array.toList() as List<NickListAdapter.IrcUserItem>
-          }
-        )
+          )
+        }
       } else {
         Observable.just(emptyList())
       }
@@ -287,8 +293,8 @@ class QuasselViewModel : ViewModel() {
                     when (info.type.toInt()) {
                       BufferInfo.Type.QueryBuffer.toInt()   -> {
                         network.liveIrcUser(info.bufferName).switchMap { user ->
-                          user.live_away.switchMap { away ->
-                            user.live_realName.map { realName ->
+                          user.liveIsAway().switchMap { away ->
+                            user.liveRealName().map { realName ->
                               BufferListAdapter.BufferProps(
                                 info = info,
                                 network = network.networkInfo(),
@@ -310,7 +316,7 @@ class QuasselViewModel : ViewModel() {
                         network.liveIrcChannel(
                           info.bufferName
                         ).switchMap { channel ->
-                          channel.live_topic.map { topic ->
+                          channel.liveTopic().map { topic ->
                             BufferListAdapter.BufferProps(
                               info = info,
                               network = network.networkInfo(),
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt
index 97b627e791ffc3e933e37af7d78fc8e236311e76..6453d805d878689536c559f678e6043ce048efa7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt
@@ -2,10 +2,11 @@ package de.kuschku.quasseldroid_ng.util.compatibility
 
 import android.util.Log
 import de.kuschku.libquassel.util.compatibility.LoggingHandler
+import de.kuschku.quasseldroid_ng.BuildConfig
 
 object AndroidLoggingHandler : LoggingHandler() {
   override fun isLoggable(logLevel: LogLevel, tag: String): Boolean {
-    return Log.isLoggable(tag, priority(logLevel))
+    return BuildConfig.DEBUG || Log.isLoggable(tag, priority(logLevel))
   }
 
   override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
index 300f25a8743c7adedc6fe6f2e31d9665fdc9bf00..dfecdbe2cb826bf273ea9ed7bcd949ef2936b349 100644
--- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt
@@ -87,12 +87,13 @@ abstract class StringSerializer(
       } else {
         val limit = buffer.limit()
         buffer.limit(buffer.position() + len - trailingNullBytes)
-        val charBuffer = charBuffer(len)
-        decoder.reset()
-        decoder.decode(buffer, charBuffer, true)
+        //val charBuffer = charBuffer(len)
+        //decoder.reset()
+        val charBuffer = decoder.charset().decode(buffer)
+        //decoder.decode(buffer, charBuffer, true)
         buffer.limit(limit)
         buffer.position(buffer.position() + trailingNullBytes)
-        charBuffer.flip()
+        //charBuffer.flip()
         charBuffer.toString()
       }
     } catch (e: Throwable) {
@@ -109,12 +110,12 @@ abstract class StringSerializer(
       } else {
         val limit = buffer.limit()
         buffer.limit(buffer.position() + Math.max(0, len - trailingNullBytes))
-        val charBuffer = charBuffer(len)
-        decoder.reset()
-        decoder.decode(buffer, charBuffer, true)
+        //val charBuffer = charBuffer(len)
+        val charBuffer = decoder.charset().decode(buffer)
+        //decoder.decode(buffer, charBuffer, true)
         buffer.limit(limit)
         buffer.position(buffer.position() + trailingNullBytes)
-        charBuffer.flip()
+        //charBuffer.flip()
         charBuffer.toString()
       }
     } catch (e: Throwable) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
index 34acb8ce5423527c150a6c6e23e1467f6af720b5..32daf7db49b996409e187e8eaa05c6dbc94ac492 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt
@@ -6,6 +6,7 @@ import de.kuschku.libquassel.quassel.syncables.interfaces.IIrcChannel
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.helpers.getOr
+import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 import java.nio.charset.Charset
 
@@ -15,6 +16,9 @@ class IrcChannel(
   proxy: SignalProxy
 ) : SyncableObject(proxy, "IrcChannel"), IIrcChannel {
   override fun init() {
+    if (name().isEmpty()) {
+      println("Error: channelName is empty")
+    }
     renameObject("${network().networkId()}/${name()}")
   }
 
@@ -79,6 +83,7 @@ class IrcChannel(
         network().newIrcUser(key) to value.value("")
       }.toMap()
     )
+    live_userModes.onNext(_userModes)
   }
 
   override fun initSetProperties(properties: QVariantMap) {
@@ -96,13 +101,30 @@ class IrcChannel(
   }
 
   fun name() = _name
+  fun liveName(): Observable<String> = live_name
+
   fun topic() = _topic
+  fun liveTopic(): Observable<String> = live_topic
+
   fun password() = _password
+  fun livePassword(): Observable<String> = live_password
+
   fun encrypted() = _encrypted
+  fun liveEncrypted(): Observable<Boolean> = live_encrypted
+
   fun network() = _network
+
   fun ircUsers() = _userModes.keys
+  fun liveIrcUsers(): Observable<MutableSet<IrcUser>> =
+    live_userModes.map(MutableMap<IrcUser, String>::keys)
+
   fun userModes(ircUser: IrcUser) = _userModes.getOr(ircUser, "")
+  fun liveUserModes(ircUser: IrcUser) = live_userModes.map {
+    _userModes.getOr(ircUser, "")
+  }
   fun userModes(nick: String) = network().ircUser(nick)?.let { userModes(it) } ?: ""
+  fun liveUserModes(nick: String) = network().ircUser(nick)?.let { userModes(it) } ?: ""
+
   fun hasMode(mode: Char) = when (network().channelModeType(mode)) {
     INetwork.ChannelModeType.A_CHANMODE ->
       _A_channelModes.contains(mode)
@@ -166,7 +188,6 @@ class IrcChannel(
     if (_topic == topic)
       return
     _topic = topic
-    live_topic.onNext(topic)
     super.setTopic(topic)
   }
 
@@ -205,6 +226,7 @@ class IrcChannel(
       _userModes[user] = modes
       user.joinChannel(this, true)
     }
+    live_userModes.onNext(_userModes)
     if (newNicks.isNotEmpty())
       super.joinIrcUsers(
         newNicks.map(Pair<IrcUser, String>::first).map(IrcUser::nick),
@@ -222,12 +244,14 @@ class IrcChannel(
     if (!isKnownUser(ircuser))
       return
     _userModes.remove(ircuser)
+    live_userModes.onNext(_userModes)
     ircuser.partChannel(this)
     if (network().isMe(ircuser) || _userModes.isEmpty()) {
       for (user in _userModes.keys) {
         user.partChannel(this)
       }
       _userModes.clear()
+      live_userModes.onNext(_userModes)
       network().removeIrcChannel(this)
       proxy.stopSynchronize(this)
     }
@@ -242,6 +266,7 @@ class IrcChannel(
     if (ircuser == null || !isKnownUser(ircuser))
       return
     _userModes[ircuser] = modes
+    live_userModes.onNext(_userModes)
     super.setUserModes(ircuser.nick(), modes)
   }
 
@@ -259,6 +284,7 @@ class IrcChannel(
     if (_userModes.getOr(ircuser, "").contains(mode, ignoreCase = true))
       return
     _userModes[ircuser] = _userModes.getOr(ircuser, "") + mode
+    live_userModes.onNext(_userModes)
     super.addUserMode(ircuser.nick(), mode)
   }
 
@@ -273,6 +299,7 @@ class IrcChannel(
       return
     _userModes[ircuser] = _userModes.getOr(ircuser, "")
       .replace(mode, "", ignoreCase = true)
+    live_userModes.onNext(_userModes)
     super.addUserMode(ircuser.nick(), mode)
   }
 
@@ -312,15 +339,36 @@ class IrcChannel(
     super.removeChannelMode(mode, value)
   }
 
-  private var _name: String = name
-  private var _topic: String = ""
-  val live_topic = BehaviorSubject.createDefault("")
-  private var _password: String = ""
-  private var _encrypted: Boolean = false
-  private var _userModes: MutableMap<IrcUser, String> = mutableMapOf()
+  private val live_name = BehaviorSubject.createDefault(name)
+  private var _name: String
+    get() = live_name.value
+    set(value) = live_name.onNext(value)
+
+  private val live_topic = BehaviorSubject.createDefault("")
+  private var _topic: String
+    get() = live_topic.value
+    set(value) = live_topic.onNext(value)
+
+  private val live_password = BehaviorSubject.createDefault("")
+  private var _password: String
+    get() = live_password.value
+    set(value) = live_password.onNext(value)
+
+  private val live_encrypted = BehaviorSubject.createDefault(false)
+  private var _encrypted: Boolean
+    get() = live_encrypted.value
+    set(value) = live_encrypted.onNext(value)
+
+  private val live_userModes = BehaviorSubject.createDefault(mutableMapOf<IrcUser, String>())
+  private var _userModes: MutableMap<IrcUser, String>
+    get() = live_userModes.value
+    set(value) = live_userModes.onNext(value)
+
   private var _network: Network = network
+
   private var _codecForEncoding: Charset? = null
   private var _codecForDecoding: Charset? = null
+
   private var _A_channelModes: MutableMap<Char, MutableSet<String>> = mutableMapOf()
   private var _B_channelModes: MutableMap<Char, String> = mutableMapOf()
   private var _C_channelModes: MutableMap<Char, String> = mutableMapOf()
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt
index c50dd64002c6fa9a86f913f5c518d81ad073e4a8..06d7c06bab8fc1a8c0e6e85197ac9207db25c0c2 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt
@@ -7,6 +7,7 @@ import de.kuschku.libquassel.protocol.valueOr
 import de.kuschku.libquassel.quassel.syncables.interfaces.IIrcUser
 import de.kuschku.libquassel.session.SignalProxy
 import de.kuschku.libquassel.util.irc.HostmaskHelper
+import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
 import org.threeten.bp.Instant
 import java.nio.charset.Charset
@@ -67,29 +68,70 @@ class IrcUser(
     setUserModes(properties["userModes"].valueOr(this::userModes))
   }
 
+  fun nick() = _nick
+  fun liveNick(): Observable<String> = live_nick
+
   fun user() = _user
+  fun liveUser(): Observable<String> = live_user
+
   fun host() = _host
-  fun nick() = _nick
+  fun liveHost(): Observable<String> = live_host
+
   fun realName() = _realName
+  fun liveRealName(): Observable<String> = live_realName
+
   fun account() = _account
+  fun liveAccount(): Observable<String> = live_account
+
   fun hostMask() = "${nick()}!${user()}@${host()}"
+  fun liveHostMask() = liveNick().switchMap { nick ->
+    liveUser().switchMap { user ->
+      liveHost().map { host ->
+        "$nick!$user@$host"
+      }
+    }
+  }
+
   fun isAway() = _away
+  fun liveIsAway(): Observable<Boolean> = live_away
+
   fun awayMessage() = _awayMessage
+  fun liveAwayMessage(): Observable<String> = live_awayMessage
+
+  fun server() = _server
+  fun liveServer(): Observable<String> = live_server
+
   fun idleTime(): Instant {
     if (Instant.now().epochSecond - _idleTimeSet.epochSecond > 1200)
       _idleTime = Instant.EPOCH
     return _idleTime
   }
 
+  fun liveIdleTime(): Observable<Instant> = live_idleTime
+
   fun loginTime() = _loginTime
-  fun server() = _server
+  fun liveLoginTime(): Observable<Instant> = live_loginTime
+
   fun ircOperator() = _ircOperator
+  fun liveIrcOperator(): Observable<String> = live_ircOperator
+
   fun lastAwayMessage() = _lastAwayMessage
+  fun liveLastAwayMessage(): Observable<Int> = live_lastAwayMessage
+
   fun whoisServiceReply() = _whoisServiceReply
+  fun liveWhoisServiceReply(): Observable<String> = live_whoisServiceReply
+
   fun suserHost() = _suserHost
+  fun liveSuserHost(): Observable<String> = live_suserHost
+
   fun encrypted() = _encrypted
+  fun liveEncrypted(): Observable<Boolean> = live_encrypted
+
   fun network() = _network
+
   fun userModes() = _userModes
+  fun liveUserModes(): Observable<String> = live_userModes
+
   fun channels() = _channels.map(IrcChannel::name)
   fun codecForEncoding() = _codecForEncoding
   fun codecForDecoding() = _codecForDecoding
@@ -119,6 +161,7 @@ class IrcUser(
 
   override fun setNick(nick: String) {
     if (nick.isNotEmpty() && _nick != nick) {
+      network().ircUserNickChanged(_nick, nick)
       _nick = nick
       updateObjectName()
       super.setNick(nick)
@@ -128,7 +171,6 @@ class IrcUser(
   override fun setRealName(realName: String) {
     if (_realName != realName) {
       _realName = realName
-      live_realName.onNext(realName)
       super.setRealName(realName)
     }
   }
@@ -143,7 +185,6 @@ class IrcUser(
   override fun setAway(away: Boolean) {
     if (_away != away) {
       _away = away
-      live_away.onNext(away)
       super.setAway(away)
     }
   }
@@ -268,29 +309,97 @@ class IrcUser(
   }
 
   fun updateObjectName() {
-    renameObject("${network().networkId()}/$_nick")
-  }
-
-  private var _nick: String = HostmaskHelper.nick(hostmask)
-  private var _user: String = HostmaskHelper.user(hostmask)
-  private var _host: String = HostmaskHelper.host(hostmask)
-  private var _realName: String = ""
-  val live_realName = BehaviorSubject.createDefault("")
-  private var _account: String = ""
-  private var _awayMessage: String = ""
-  private var _away: Boolean = false
-  val live_away = BehaviorSubject.createDefault(false)
-  private var _server: String = ""
-  private var _idleTime: Instant = Instant.EPOCH
-  private var _idleTimeSet: Instant = Instant.EPOCH
-  private var _loginTime: Instant = Instant.EPOCH
-  private var _ircOperator: String = ""
-  private var _lastAwayMessage: Int = 0
-  private var _whoisServiceReply: String = ""
-  private var _suserHost: String = ""
-  private var _encrypted: Boolean = false
+    val identifier = "${network().networkId()}/${nick()}"
+    renameObject(identifier)
+  }
+
+  private val live_nick = BehaviorSubject.createDefault(HostmaskHelper.nick(hostmask))
+  private var _nick: String
+    get() = live_nick.value
+    set(value) = live_nick.onNext(value)
+
+  private val live_user = BehaviorSubject.createDefault(HostmaskHelper.user(hostmask))
+  private var _user: String
+    get() = live_user.value
+    set(value) = live_user.onNext(value)
+
+  private val live_host = BehaviorSubject.createDefault(HostmaskHelper.host(hostmask))
+  private var _host: String
+    get() = live_host.value
+    set(value) = live_host.onNext(value)
+
+  private val live_realName = BehaviorSubject.createDefault("")
+  private var _realName: String
+    get() = live_realName.value
+    set(value) = live_realName.onNext(value)
+
+  private val live_account = BehaviorSubject.createDefault("")
+  private var _account: String
+    get() = live_account.value
+    set(value) = live_account.onNext(value)
+
+  private val live_awayMessage = BehaviorSubject.createDefault("")
+  private var _awayMessage: String
+    get() = live_awayMessage.value
+    set(value) = live_awayMessage.onNext(value)
+
+  private val live_away = BehaviorSubject.createDefault(false)
+  private var _away: Boolean
+    get() = live_away.value
+    set(value) = live_away.onNext(value)
+
+  private val live_server = BehaviorSubject.createDefault("")
+  private var _server: String
+    get() = live_server.value
+    set(value) = live_server.onNext(value)
+
+  private val live_idleTime = BehaviorSubject.createDefault(Instant.EPOCH)
+  private var _idleTime: Instant
+    get() = live_idleTime.value
+    set(value) = live_idleTime.onNext(value)
+
+  private val live_idleTimeSet = BehaviorSubject.createDefault(Instant.EPOCH)
+  private var _idleTimeSet: Instant
+    get() = live_idleTimeSet.value
+    set(value) = live_idleTimeSet.onNext(value)
+
+  private val live_loginTime = BehaviorSubject.createDefault(Instant.EPOCH)
+  private var _loginTime: Instant
+    get() = live_loginTime.value
+    set(value) = live_loginTime.onNext(value)
+
+  private val live_ircOperator = BehaviorSubject.createDefault("")
+  private var _ircOperator: String
+    get() = live_ircOperator.value
+    set(value) = live_ircOperator.onNext(value)
+
+  private val live_lastAwayMessage = BehaviorSubject.createDefault(0)
+  private var _lastAwayMessage: Int
+    get() = live_lastAwayMessage.value
+    set(value) = live_lastAwayMessage.onNext(value)
+
+  private val live_whoisServiceReply = BehaviorSubject.createDefault("")
+  private var _whoisServiceReply: String
+    get() = live_whoisServiceReply.value
+    set(value) = live_whoisServiceReply.onNext(value)
+
+  private val live_suserHost = BehaviorSubject.createDefault("")
+  private var _suserHost: String
+    get() = live_suserHost.value
+    set(value) = live_suserHost.onNext(value)
+
+  private val live_encrypted = BehaviorSubject.createDefault(false)
+  private var _encrypted: Boolean
+    get() = live_encrypted.value
+    set(value) = live_encrypted.onNext(value)
+
   private var _channels: MutableSet<IrcChannel> = mutableSetOf()
-  private var _userModes: String = ""
+
+  private val live_userModes = BehaviorSubject.createDefault("")
+  private var _userModes: String
+    get() = live_userModes.value
+    set(value) = live_userModes.onNext(value)
+
   private var _network: Network = network
   private var _codecForEncoding: Charset? = null
   private var _codecForDecoding: Charset? = null
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
index 246741dd42659ebab82c3500008bb09877219b5b..e0be80108be439ec05e5a3857ac6a091226277ab 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt
@@ -262,7 +262,7 @@ class Network constructor(
     }
   }
 
-  fun supports(param: String) = _supports.contains(param.toUpperCase(Locale.ENGLISH))
+  fun supports(param: String) = _supports.contains(param.toUpperCase(Locale.US))
   fun support(param: String) = _supports.getOr(param, "")
   /**
    * Checks if a given capability is advertised by the server.
@@ -274,8 +274,7 @@ class Network constructor(
    * @param capability Name of capability
    * @return True if connected and advertised by the server, otherwise false
    */
-  fun capAvailable(capability: String)
-    = _caps.contains(capability.toLowerCase(Locale.ENGLISH))
+  fun capAvailable(capability: String) = _caps.contains(capability.toLowerCase(Locale.US))
 
   /**
    * Checks if a given capability is acknowledged and active.
@@ -283,8 +282,7 @@ class Network constructor(
    * @param capability Name of capability
    * @return True if acknowledged (active), otherwise false
    */
-  fun capEnabled(capability: String)
-    = _capsEnabled.contains(capability.toLowerCase(Locale.ENGLISH))
+  fun capEnabled(capability: String) = _capsEnabled.contains(capability.toLowerCase(Locale.US))
 
   /**
    * Gets the value of an available capability, e.g. for SASL, "EXTERNAL,PLAIN".
@@ -292,8 +290,7 @@ class Network constructor(
    * @param capability Name of capability
    * @return Value of capability if one was specified, otherwise isEmpty string
    */
-  fun capValue(capability: String)
-    = _caps.getOr(capability.toLowerCase(Locale.ENGLISH), "")
+  fun capValue(capability: String) = _caps.getOr(capability.toLowerCase(Locale.US), "")
 
   /**
    * Check if the given authentication mechanism is likely to be supported.
@@ -323,7 +320,7 @@ class Network constructor(
   }
 
   fun newIrcUser(hostMask: String, initData: QVariantMap = emptyMap()): IrcUser {
-    val nick = HostmaskHelper.nick(hostMask).toLowerCase(Locale.ENGLISH)
+    val nick = HostmaskHelper.nick(hostMask).toLowerCase(Locale.US)
     val user = ircUser(nick)
     return if (user == null) {
       val ircUser = IrcUser(hostMask, this, proxy)
@@ -343,7 +340,7 @@ class Network constructor(
     }
   }
 
-  fun ircUser(nickName: String?) = _ircUsers[nickName?.toLowerCase(Locale.ENGLISH)]
+  fun ircUser(nickName: String?) = _ircUsers[nickName?.toLowerCase(Locale.US)]
   fun liveIrcUser(nickName: String?) = live_ircUsers.map {
     ircUser(
       nickName
@@ -362,7 +359,7 @@ class Network constructor(
         ircChannel.initialized = true
       }
       proxy.synchronize(ircChannel)
-      _ircChannels[channelName.toLowerCase(Locale.ENGLISH)] = ircChannel
+      _ircChannels[channelName.toLowerCase(Locale.US)] = ircChannel
       live_ircChannels.onNext(_ircChannels)
       super.addIrcChannel(channelName)
       return ircChannel
@@ -371,7 +368,7 @@ class Network constructor(
     }
   }
 
-  fun ircChannel(channelName: String?) = _ircChannels[channelName?.toLowerCase(Locale.ENGLISH)]
+  fun ircChannel(channelName: String?) = _ircChannels[channelName?.toLowerCase(Locale.US)]
   fun liveIrcChannel(channelName: String?) = live_ircChannels.map {
     ircChannel(
       channelName
@@ -644,12 +641,12 @@ class Network constructor(
   }
 
   override fun addCap(capability: String, value: String) {
-    _caps[capability.toLowerCase(Locale.ENGLISH)] = value
+    _caps[capability.toLowerCase(Locale.US)] = value
     super.addCap(capability, value)
   }
 
   override fun acknowledgeCap(capability: String) {
-    val lowerCase = capability.toLowerCase(Locale.ENGLISH)
+    val lowerCase = capability.toLowerCase(Locale.US)
     if (!_capsEnabled.contains(lowerCase))
       return
     _capsEnabled.add(lowerCase)
@@ -657,7 +654,7 @@ class Network constructor(
   }
 
   override fun removeCap(capability: String) {
-    val lowerCase = capability.toLowerCase(Locale.ENGLISH)
+    val lowerCase = capability.toLowerCase(Locale.US)
     if (!_caps.contains(lowerCase))
       return
     _caps.remove(lowerCase)
@@ -842,7 +839,7 @@ class Network constructor(
   }
 
   fun updateNickFromMask(mask: String): IrcUser {
-    val nick = HostmaskHelper.nick(mask).toLowerCase(Locale.ENGLISH)
+    val nick = HostmaskHelper.nick(mask).toLowerCase(Locale.US)
     val user = _ircUsers[nick]
     return if (user != null) {
       user.updateHostmask(mask)
@@ -852,8 +849,11 @@ class Network constructor(
     }
   }
 
-  override fun ircUserNickChanged(newnick: String) {
-    throw RuntimeException("Look at this: $newnick")
+  override fun ircUserNickChanged(old: String, new: String) {
+    val value = _ircUsers.remove(old.toLowerCase(Locale.US))
+    if (value != null) {
+      _ircUsers[new.toLowerCase(Locale.US)] = value
+    }
   }
 
   override fun emitConnectionError(error: String) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
index 91fa2511423ca450d3c04e8e9fcd2fa9cb24b4be..893561e95d77f134ab44c0d383117c310638eb53 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
@@ -9,20 +9,20 @@ abstract class SyncableObject(
 ) : ISyncableObject {
   final override var objectName: String = ""
     private set
-  override var identifier: String = "$className:"
+  override var identifier = Pair(className, objectName)
   override var initialized: Boolean = false
 
   protected fun renameObject(newName: String) {
     val oldName = objectName
     if (!initialized) {
       objectName = newName
-      identifier = "$className:$objectName"
+      identifier = Pair(className, objectName)
     } else if (oldName != newName) {
       objectName = newName
-      identifier = "$className:$objectName"
+      identifier = Pair(className, objectName)
       proxy.renameObject(this, newName, oldName)
     }
   }
 
-  override fun toString() = identifier
+  override fun toString() = "${identifier.first}:${identifier.second}"
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
index 02c7d6de8902423d4cadf28a40a516b78b4a1863..9dc0caa42dfc65843dd737dee883a3556120911c 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt
@@ -62,7 +62,7 @@ interface INetwork : ISyncableObject {
   }
 
   @Slot
-  fun ircUserNickChanged(newnick: String)
+  fun ircUserNickChanged(old: String, new: String)
 
   @Slot
   fun removeCap(capability: String) {
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
index fa2d663addeea8ae46d435ed89f1460ac12a88d9..3c557684324a3d5a21bff236b323700cdbc65645 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
@@ -8,7 +8,7 @@ import de.kuschku.libquassel.session.SignalProxy
 
 interface ISyncableObject {
   val objectName: String
-  var identifier: String
+  var identifier: Pair<String, String>
   val className: String
   var initialized: Boolean
   val proxy: SignalProxy
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
index c1ad35b6827792e23063cb0d41107e5e4c3dd469..5bb8962dfbd1dd0e047eeedf115d68b9607a2777 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt
@@ -8,32 +8,55 @@ import de.kuschku.libquassel.quassel.exceptions.ObjectNotFoundException
 import de.kuschku.libquassel.quassel.syncables.interfaces.ISyncableObject
 
 class ObjectStorage(private val proxy: SignalProxy) {
-  private val objectTree: MutableMap<String, ISyncableObject> = HashMap()
+  private val objectTree: MutableMap<Pair<String, String>, ISyncableObject> = HashMap()
 
-  fun add(obj: ISyncableObject) = objectTree.put(obj.identifier, obj)
+  fun add(obj: ISyncableObject) {
+    objectTree[obj.identifier] = obj
+    if (get(obj.className, obj.objectName) != obj) {
+      throw IllegalStateException("Object should be existing")
+    }
+  }
 
-  fun remove(obj: ISyncableObject) = objectTree.remove(obj.identifier)
+  fun remove(obj: ISyncableObject) {
+    objectTree.remove(obj.identifier)
+    if (get(obj.className, obj.objectName) == obj) {
+      throw IllegalStateException("Object should not be existing")
+    }
+  }
 
   fun rename(className: String, new: String, old: String) {
-    val obj = get(className, old) ?: throw ObjectNotFoundException(className, old)
-    rename(obj, new, old)
+    val obj = get(className, old)
+    if (obj != null) {
+      rename(obj, new, old)
+    } else {
+      throw ObjectNotFoundException(className, old)
+    }
   }
 
   fun rename(obj: ISyncableObject, new: String, old: String) {
-    objectTree.put("${obj.className}:$new", obj)
-    objectTree.remove("${obj.className}:$old")
-    proxy.dispatch(
-      SignalProxyMessage.RpcCall(
-        "__objectRenamed__", listOf(
-        QVariant_(obj.className, Type.QString), QVariant_(new, Type.QString),
-        QVariant_(old, Type.QString)
-      )
+    objectTree[Pair(obj.className, new)] = obj
+    objectTree.remove(Pair(obj.className, old), obj)
+    if (get(obj.className, new) != obj) {
+      throw IllegalStateException("Object should be existing")
+    }
+    if (get(obj.className, old) == obj) {
+      throw IllegalStateException("Object should not be referenced by the old name")
+    }
+    if (proxy.shouldRpc("__objectRenamed__")) {
+      proxy.dispatch(
+        SignalProxyMessage.RpcCall(
+          "__objectRenamed__",
+          listOf(
+            QVariant_(obj.className, Type.QString), QVariant_(new, Type.QString),
+            QVariant_(old, Type.QString)
+          )
+        )
       )
-    )
+    }
   }
 
   fun get(className: QType, objectName: String) = get(className.typeName, objectName)
-  fun get(className: String, objectName: String) = objectTree["$className:$objectName"]
+  fun get(className: String, objectName: String) = objectTree[Pair(className, objectName)]
 
   fun clear() = objectTree.clear()
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
index bf67186a9242d5b5ee6f7931125ab61e6e194a7d..8675961766be81e7957fd9d775153ce4e27ec585 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt
@@ -161,7 +161,7 @@ abstract class ProtocolHandler : SignalProxy, AuthHandler, Closeable {
 
     if (!syncableObject.initialized) {
       if (baseInit) {
-        toInit.put(syncableObject, mutableListOf())
+        toInit[syncableObject] = mutableListOf()
         totalInitCount++
       }
       dispatch(SignalProxyMessage.InitRequest(syncableObject.className, syncableObject.objectName))