KFStatsX Tracking Server

Тема в разделе "Технические вопросы", создана пользователем Arckon., 23 ноя 2017.

  1. Arckon.

    Arckon. Соучастник

    Приветствую. Перейду сразу к описанию проблемы.

    Имеется мутатор KFStatsX (TWI-link). Он дает возможность любому игроку на Сервере видеть статистику как индивидуальную, так и суммарную в течение текущей сессии. Выводится отдельной вкладкой в esc-меню Сервера. При возобновлении очередной сессии счетчик сбрасывается на изначальные параметры и ведется новая статистика. Вся работа выполняется в рамках игрового Сервера (пример).

    Разработчик предусмотрел выведение статистики в отдельную Базу Данных, к которой доступ есть у любого желающего изучить те или иные конфигурационные особенности статистики или же просто просмотреть желаемую информацию о любом игроке: есть возможность видеть как статистику (опять же) индивидуального игрока, так и суммарную в зависимости от предпочтений. (примеры 1 и 2). TWI-link.

    Конфигурация мутатора представлена ниже:
    [KFStatsX.KFSXMutator]
    broadcastStats=
    useV3Packets=
    ServerPort=
    ServerAddress=
    serverPwd=
    localHostSteamId=
    PlayerController=KFStatsX.KFSXPlayerController
    compatibleControllers=KFStatsX.KFSXPlayerController;Vanilla KF

    Так как нормальная инструкция отсутствовала, товарищ Arthur88 сделал небольшой туториал по установке. После некоторого количества времени, потраченного на тестирование и аналитику статистики, зафиксированной в Базе Данных, оказалось, что вкладка в навигации Perks, взятого для индивидуального игрока, имеет неправильное отображение уровня перка (например, при большом количестве единиц статистика может выдать уровень выше 6-ого, что для классики не является нормой). Было решено выпилить показание перков ввиду неэффективности и ненадобности. Туториал имеет 2 версии: With Perk-Progression и Without Perk-Progression. Файл настройки и *.ini-файл настройки конфигурации также имеются.

    Далее. После того, как игроки заходят на Сервер, они отображаются уже в Базе Данных, что дает возможность видеть их действия: историю активности на картах и пр. параметры, в т.ч. ссылка на профиль в Steam. Однако, при переходе на статистику некоторых игроков транслирующий сервер в браузере выкидывает ошибку по типу:
    500 Internal Server Error

    java.lang.NullPointerException: Cannot execute null+null
    at org.codehaus.groovy.runtime.NullObject.plus(NullObject.java:121)
    at org.codehaus.groovy.runtime.NullObject$plus.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:32)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:55)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at org.codehaus.groovy.runtime.dgmimpl.NumberNumberPlus$IntegerInteger.call(NumberNumberPlus.java:379)
    at PlayerDifficulty$_getData_closure2_closure3.doCall(PlayerDifficulty.groovy:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.Closure.call(Closure.java:411)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.callClosureForMapEntry(DefaultGroovyMethods.java:3874)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1355)
    at org.codehaus.groovy.runtime.dgm$149.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at PlayerDifficulty$_getData_closure2.doCall(PlayerDifficulty.groovy:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.Closure.call(Closure.java:411)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.callClosureForMapEntry(DefaultGroovyMethods.java:3874)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1355)
    at org.codehaus.groovy.runtime.dgm$149.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at PlayerDifficulty.getData(PlayerDifficulty.groovy:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:361)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:137)
    at GoogleChartsCreator$_create_closure1.doCall(GoogleChartsCreator.groovy:24)
    at GoogleChartsCreator$_create_closure1.doCall(GoogleChartsCreator.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at groovy.json.JsonDelegate.cloneDelegateAndGetContent(JsonDelegate.groovy:50)
    at groovy.json.JsonDelegate$cloneDelegateAndGetContent.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at groovy.json.JsonDelegate$cloneDelegateAndGetContent.call(Unknown Source)
    at groovy.json.JsonBuilder.call(JsonBuilder.groovy:148)
    at groovy.json.JsonBuilder$call.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at GoogleChartsCreator.create(GoogleChartsCreator.groovy:22)
    at DataCreator$create.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at DataCreator$create.call(Unknown Source)
    at DataDispatcher.generatePage(DataDispatcher.groovy:44)
    at DataDispatcher$generatePage.call(Unknown Source)
    at IndexHtml$_fillVisualizationJS_closure2.doCall(IndexHtml.groovy:41)
    at sun.reflect.GeneratedMethodAccessor20.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.Closure.call(Closure.java:411)
    at groovy.lang.Closure.call(Closure.java:427)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1326)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1298)
    at org.codehaus.groovy.runtime.dgm$148.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at IndexHtml.fillVisualizationJS(IndexHtml.groovy:35)
    at sun.reflect.GeneratedMethodAccessor63.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:361)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at WebPageBase$_generatePage_closure1_closure2.doCall(WebPageBase.groovy:76)
    at WebPageBase$_generatePage_closure1_closure2.doCall(WebPageBase.groovy)
    at sun.reflect.GeneratedMethodAccessor60.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.Closure.call(Closure.java:411)
    at groovy.lang.Closure.call(Closure.java:405)
    at groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:143)
    at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:64)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at WebPageBase$_generatePage_closure1.doCall(WebPageBase.groovy:61)
    at WebPageBase$_generatePage_closure1.doCall(WebPageBase.groovy)
    at sun.reflect.GeneratedMethodAccessor59.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.Closure.call(Closure.java:411)
    at groovy.lang.Closure.call(Closure.java:405)
    at groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:143)
    at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:64)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at WebPageBase.generatePage(WebPageBase.groovy:60)
    at WebPageBase$generatePage.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at DataDispatcher$generatePage.call(Unknown Source)
    at com.github.etsai.kfsxtrackingserver.web.WebHandler.serve(WebHandler.groovy:107)
    at fi.iki.elonen.NanoHTTPD.serve(NanoHTTPD.java:259)
    at fi.iki.elonen.NanoHTTPD$HTTPSession.execute(NanoHTTPD.java:778)
    at fi.iki.elonen.NanoHTTPD$1$1.run(NanoHTTPD.java:167)
    at java.lang.Thread.run(Unknown Source)
    Данная проблема случается лишь с некоторыми игроками.
    С позволения Arthur88 прикреплю статистику, чтобы увидеть проблему. Достаточно пробежаться по профилям некоторых игроков. Еще пример Базы Данных. Шутки про non-steam клиентов и Server Perks не очень будут уместны. Просьба помочь разобраться или объяснить, как решить данную проблему.

    Ссылка на Форум TWI
    Ссылка на Исходники автора
    Ccылка на WorkShop
     
    Последнее редактирование: 24 ноя 2017
    Фрэгл и Flame нравится это.
  2. Flame

    Flame -Заслуженый кодер форума-

    Вот когда всё так красиво оформлено у меня нет шанса не поучаствовать)
    Тем более что давно собираюсь сделать себе аналогичный мутатор (а этот использую на классическом стим серваке)
    Изучу вопрос
     
    Arthur88, Essence и Arckon. нравится это.
  3. STaJIKeR

    STaJIKeR Капо

    Если в статистике есть SteamID в открытом доступе, это уже непорядок, плохие люди могут использовать это в плохих целях (подмена ID например).
     
    Essence нравится это.