CMP - форум PRO игроков казино

Отзывы, советы экспертов и лучшие стратегии - для успешной игры в казино!

Roulette MEGA Tracker (RMT) - калькулятор ставок Шпилевого

  • Axsee
  • Axsee аватар
  • nub
  • nub
  • Сообщений: 63

Re: Roulette MEGA Tracker (RMT) - калькулятор ставок Шпилевого

1 год 1 мес. назад
#25
Ждем, ждем:)

В разное время игры одни атомы разгоняют депозит, другие сливают. 
Но в старом приложении не совсем удобно между атомами перемещаться.
Интересно возможно ли реализовать, что бы прогнозы со всех атомов отображались на одном экране?
Хотя возможно места не хватит для интерфейса.
Спасибо сказали: LUCKY-13, Shpilevoy

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

  • Shpilevoy
  • Shpilevoy аватар Автор темы
  • VIP
  • VIP
  • ∻♥♚ RMT ♚♥∻
  • Сообщений: 5066

Re: Roulette MEGA Tracker (RMT) - калькулятор ставок Шпилевого

1 год 1 мес. назад
#26
Возможно. Скроллинг экрана и компонент ScrollView в Unity = нет никаких ограничений по ширине и высоте контента.
►ИДЕАЛЬНЫЙ ИГРОК RMT
Loading… ███████[][][] 70%

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

  • Shpilevoy
  • Shpilevoy аватар Автор темы
  • VIP
  • VIP
  • ∻♥♚ RMT ♚♥∻
  • Сообщений: 5066

Re: Roulette MEGA Tracker (RMT) - калькулятор ставок Шпилевого

1 год 1 нед. назад - 1 год 1 нед. назад
#27
Лучшее = враг хорошего )))
Прошла первая волна реальных испытаний на разных рулетках, в разных условиях, в разных казино.
Надо сказать, что в земных казино питы не дремлют = сразу подбегают смотреть, чем там человек на телефоне занимается )))

/////////////////////

Все предыдущие наработки ушли под нож (кроме внутренней механики).
Нейросети сдохли вообще = нулевая эффективность.
Атомы и БРМ затачиваются во взаимодействии.
Спасибо, всем кто помогал тестить прилу и оставил практические отзывы. Сейчас я все это пересматриваю и переделываю прогу, чтобы она была СВЕРХ-УДОБНОЙ.

/////////////////////

Новые интерфейсы, новая структура программы === НОВОЕ НАЗВАНИЕ.



Прошу Админа поменять название этой темы.
RMT
ROULETTE MEGA TRACKER

Еще пара месяцев переделок, испытаний и тестов, окончательной полировки алгоритмов
=== в ранний доступ прилу можно будет выкладывать
►ИДЕАЛЬНЫЙ ИГРОК RMT
Loading… ███████[][][] 70%
Спасибо сказали: Coin, mouse, WoodForest

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

  • Coin
  • Coin аватар
  • moder
  • moder
  • ☜♡☞ Roulette foreva ☜♡☞
  • Сообщений: 888

Re: Roulette MEGA Tracker (RMT) - калькулятор ставок Шпилевого

1 год 1 нед. назад
#28
Заинтриговал. Ждемс-с-с-с.
☜♡☞ Roulette foreva ☜♡☞
Спасибо сказали: Shpilevoy, mouse

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

  • Shpilevoy
  • Shpilevoy аватар Автор темы
  • VIP
  • VIP
  • ∻♥♚ RMT ♚♥∻
  • Сообщений: 5066

Re: Roulette MEGA Tracker (RMT) - калькулятор ставок Шпилевого

11 мес. 3 нед. назад - 11 мес. 3 нед. назад
#29
ЗАВЕРШАЮЩИЙ ЭТАП КОДИНГА!
///////////////////////////////

Так. Столкнулся с неожиданной проблемой в редакторе UNITY =
При активации 6+ атомов прога начинает неожиданно и произвольно зависать. Ошибки не выдает! Музыка фоновая продолжает играть, а редактор в режиме выполнения крепко висит...

Мне такая ОШИБКА не подходит ))) Мега-трекер со временем будет иметь много атомов = именно под такую НЕОГРАНИЧЕННУЮ структуру все и планировалось.

Нашел хорошую статью по оптимизации проекта..... выполнил только первые два правила...
и ОШИБКА ИСЧЕЗЛА!

Сохраню эту статью на всякий случай )))
///////////////////////////////

Первое правило: никаких новых объектов в методах Update
В идеале методы Update, FixedUpdate и LateUpdate не должны содержать ключевых слов «new». Всегда нужно использовать то, что у вас уже есть.

Иногда создание нового объекта сокрыто в некоторых внутренних методах Unity, поэтому оно не так очевидно. Мы расскажем об этом позже.

Второе правило: создавать один раз и использовать многократно!
По сути, это означает, что выделять память для всего, что можно, следует в методах Start и Awake. Это правило очень похоже на первое. На самом деле это просто ещё один способ устранения ключевых слов «new» из методов Update.

Код, который:

создаёт новые экземпляры ищет какие-нибудь игровые объекты
следует всегда стараться перемещать из методов Update в Start или Awake.

Вот примеры внесённых нами изменений:

Выделение памяти под списки в методе Start, их очистка (Clear) и повторное использование при необходимости.

//Bad codeprivate List<GameObject> objectsList;void Update(){
objectsList = new List<GameObject>(); objectsList.Add(......)
}
//Better Codeprivate List<GameObject> objectsList;void Start(){
objectsList = new List<GameObject>();}
void Update(){
objectsList.Clear();
objectsList.Add(......)
}
Хранение ссылок и повторное использование их следующим образом:

//Bad codevoid Update(){
var levelObstacles = FindObjectsOfType<Obstacle>(); foreach(var obstacle in levelObstacles) { ....... }}
//Better codeprivate Object[] levelObstacles;void Start(){
levelObstacles = FindObjectsOfType<Obstacle>();
}
void Update(){
foreach(var obstacle in levelObstacles) { ....... }}
То же относится к методу FindGameObjectsWithTag или любому другому методу, возвращающему новый массив.

Третье правило: остерегайтесь строк и избегайте их конкатенации
Когда дело доходит до создания мусора, то строки ужасны. Даже простейшие операции со строками могут создавать много мусора. Почему? Строки — это просто массивы, и эти массивы неизменяемы (immutable). Это означает, что каждый раз, когда вы конкатенируете две строки, создаётся новый массив, а старый превращается в мусор. К счастью, можно использовать StringBuilder, чтобы избежать или минимизировать такое создание мусора.

Вот пример того, как можно улучшить ситуацию:

//Bad codevoid Start(){
text = GetComponent<Text>();
}
void Update(){
text.text = "Player " + name + " has score " + score.toString();}
//Better codevoid Start(){
text = GetComponent<Text>();
builder = new StringBuilder(50);}
void Update(){
//StringBuilder has overloaded Append method for all types builder.Length = 0; builder.Append("Player "); builder.Append(name);
builder.Append(" has score "); builder.Append(score);
text.text = builder.ToString();
}
С показанным выше примером всё в порядке, но в нём есть ещё много возможностей для улучшения кода. Как видите, почти всю строку можно считать статической. Мы разделяем строку на две части для двух объектов UI.Text. Сначала одна содержит только статический текст «Player » + name + " has score ", который можно назначить в методе Start, а вторая содержит значение счёта, которое обновляется в каждом кадре. Всегда делайте статические строки действительно статическими и генерируйте их в методе Start или Awake. После этого усовершенствования почти всё в порядке, но по-прежнему генерируется немного мусора при вызове Int.ToString(), Float.ToString() и т.п.

Мы решили эту проблему генерацией и предварительным выделением памяти под все возможные строки. Это может показаться глупой тратой памяти, но такое решение идеально соответствует нашим потребностям и полностью решает проблему. Итак, в конечном итоге мы получили статический массив, доступ к которому можно напрямую получать доступ при помощи индексов, чтобы брать нужную строку, обозначающую число:

public static readonly string[] NUMBERS_THREE_DECIMAL = { "000", "001", "002", "003", "004", "005", "006",..........

Четвёртое правило: кешировать значения, возвращаемые методами доступа
Это может быть очень сложно, потому что даже простой метод доступа (accessor), наподобие показанного ниже, генерирует мусор:

//Bad Codevoid Update(){
gameObject.tag;
//or gameObject.name;
}
Старайтесь избегать использования методов доступа в методе Update. Вызывайте метод доступа только один раз в методе Start и кешируйте возвращаемое значение.

В общем случае я рекомендую НЕ вызывать никаких методов доступа к строкам или методов доступа к массивам в методе Update. В большинстве случаев достаточно один раз получить ссылку в методе Start.

Вот ещё два распространённых примера ещё одного неоптимизированного кода методов доступа:

//Bad Codevoid Update(){
//Allocates new array containing all touches Input.touches[0];}
//Better Codevoid Update(){
Input.GetTouch(0);}
//Bad Codevoid Update(){
//Returns new string(garbage) and compare the two strings gameObject.Tag == "MyTag";}
//Better Codevoid Update(){
gameObject.CompareTag("MyTag");}
Пятое правило: используйте функции, не выполняющие выделение памяти
Для некоторых функций Unity можно найти альтернативы, не выделяющие память. В нашем случае все эти функции связаны с физикой. Наше распознавание коллизий основано на

Physics2D. CircleCast();
Для этого конкретного случая можно найти не выделяющую память функцию под названием

Physics2D. CircleCastNonAlloc();
Многие другие функции тоже имеют подобные альтернативы, поэтому всегда проверяйте в документации наличие NonAlloc-функций.

Шестое правило: не используйте LINQ
Просто не делайте этого. Я имею в виду, что не нужно использовать его в любом коде, который выполняется часто. Знаю, при использовании LINQ код проще читается, но во многих случаях производительность и выделение памяти такого кода ужасны. Разумеется, его можно иногда использовать, но, если честно, в своей игре мы вообще не применяем LINQ.

Седьмое правило: создавать один раз и использовать многократно, часть 2
На этот раз речь идёт о пулинге объектов. 

В нашем случае используется следующий сценарий пулинга объектов. У нас есть сгенерированный уровень, заполненный препятствиями, существующими в течение определённого периода времени, пока игрок не пройдёт эту часть уровня. Экземпляры таких препятствий создаются из префабов в случае соблюдения определённых условий. Код находится в методе Update. Этот код совершенно неэффективен с точки зрения памяти и времени выполнения. Мы решили проблему, сгенерировав пул из 40 препятствий: при необходимости мы получаем препятствия из пула и возвращаем объект обратно в пул, когда он больше не нужен.

Восьмое правило: внимательнее с упаковкой-преобразованием (Boxing)!
Boxing генерирует мусор! Но что такое boxing? Чаще всего boxing возникает, когда вы передаёте тип значения (int, float, bool и т.д.) в функцию, которая ожидает параметр типа Object.

Вот пример boxing-а который нам нужно исправить в нашем проекте:

Мы реализовали в проекте собственную систему сообщений. Каждое сообщение может содержать неограниченное количество данных. Данные хранятся в словаре, задаваемом следующим образом:

Dictionary<string, object> data;
Также у нас есть сеттер, задающий значения в этом словаре:

public Action SetAttribute(string attribute, object value){
data[attribute] = value;}
Boxing здесь довольно очевиден. Можно вызвать функцию следующим образом:

SetAttribute("my_int_value", 12);
Тогда значение «12» подвергается boxing-у и это генерирует мусор.

Мы решили проблему, создав отдельные контейнеры данных для каждого примитивного типа, а предыдущий контейнер Object используется только для типов-ссылок.

Dictionary<string, object> data;Dictionary<string, bool> dataBool;Dictionary<string, int> dataInt;.......
Также у нас есть отдельные сеттеры для каждого типа данных:

SetBoolAttribute(string attribute, bool value)SetIntAttribute(string attribute, int value)
И все эти сеттеры реализованы таким образом, что вызывают одинаковую обобщённую функцию:

SetAttribute<T>(ref Dictionary<string, T> dict, string attribute, T value)
Проблема boxing-а решена!

Девятое правило: циклы всегда под подозрением
Это правило очень похоже на первое и второе. Просто старайтесь убрать весь необязательный код из циклов из соображений производительности и выделения памяти.

В общем случае мы стремимся избавиться от циклов в методах Update, но если без них не обойтись, то мы по крайней мере избегаем любого выделения памяти в таких циклах. Итак, следуйте правилам 1–8 и примените их к циклам в целом, а не только в методах Update.

Десятое правило: никакого мусора во внешних библиотеках
В случае, если выяснится, что часть мусора генерируется кодом, скачанным из Asset store, то у этой проблемы есть множество вариантов решения. Но прежде чем выполнять реверс-инжиниринг и отладку, просто снова зайдите в Asset store и обновите библитеку. В нашем случае все используемые ассеты по-прежнему поддерживались авторами, продолжающими выпускать улучшающие производительность обновления, поэтому это решило все наши проблемы. Зависимости должны быть актуальными! Я лучше избавлюсь от библиотеки, чем сохраню неподдерживаемую.

Часть 2: максимально снижаем время выполнения
Некоторые из представленных выше правил вносят едва заметную разницу, если код вызывается редко. В нашем коде есть один большой цикл, выполняемый в каждом кадре, поэтому даже эти небольшие изменения оказали огромный эффект.

Некоторые из таких изменений при неверном использовании или в неподходящей ситуации могут приводить к ещё большему ухудшению времени выполнения. Всегда проверяйте профилировщик после внесения в код каждой оптимизации, чтобы убедиться, что вы двигаетесь в верном направлении.

Честно говоря, некоторые из этих правил приводят к гораздо хуже читаемому коду, а иногда даже нарушают рекомендации, например, упомянутое в одном из представленных ниже правил встраивание кода.

Многие из этих правил пересекаются с представленными в первой части статьи. Обычно производительность создающего мусор кода ниже по сравнению с кодом без создания мусора.

Первое правило: правильный порядок выполнения
Переместите код из методов FixedUpdate, Update, LateUpdate в методы Start и Awake. Знаю, это звучит безумно, но поверьте, если вы углубитесь в свой код, то найдёте сотни строк кода, которые можно переместить в методы, исполняемые только один раз.

В нашем случае такой код обычно связан с

Вызовами GetComponent<>Вычислениями, которые на самом деле возвращают в каждом кадре одинаковый результатМногократным созданием экземпляров одних и тех же объектов, обычно списковПоиском GameObjectsПолучением ссылок на Transform и использованием других методов доступа
Вот список примеров кода, который мы переместили из методов Update в методы Start:

//There must be a good reason to keep GetComponent in UpdategameObject.GetComponent<LineRenderer>();
gameObject.GetComponent<CircleCollider2D>();

//Examples of calculations returning same result every frameMathf.FloorToInt(Screen.width / 2);var width = 2f * mainCamera.orthographicSize * mainCamera.aspect;var castRadius = circleCollider.radius * transform.lossyScale.x;var halfSize = GetComponent<SpriteRenderer>().bounds.size.x / 2f;//Finding objectsvar levelObstacles = FindObjectsOfType<Obstacle>();var levelCollectibles = FindGameObjectsWithTag("COLLECTIBLE");//ReferencesobjectTransform = gameObject.transform;
mainCamera = Camera.main;
Второе правило: выполняйте код только тогда, когда это необходимо
В нашем случае это в основном относилось к скриптам обновления UI. Вот пример того, как мы изменили реализацию кода, отображающего текущее состояние собираемых предметов на уровне.

//Bad codeText text;
GameState gameState;

void Start(){
gameState = StoreProvider.Get<GameState>();
text = GetComponent<Text>();
}

void Update(){
text.text = gameState.CollectedCollectibles.ToString();
}
Так как на каждом уровне есть всего несколько собираемых предметов, то не имеет никакого смысла изменять текст UI в каждом кадре. Поэтому мы изменяем текст только при изменении числа.

//Better codeText text;
GameState gameState;
int collectiblesCount;void Start(){
gameState = StoreProvider.Get<GameState>();
text = GetComponent<Text>();
collectiblesCount = gameState.CollectedCollectibles;
}

void Update(){
if(collectiblesCount != gameState.CollectedCollectibles) {
//This code is ran only about 5 times each level collectiblesCount = gameState.CollectedCollectibles;
text.text = collectiblesCount.ToString();
}
}
Этот код гораздо лучше, особенно если действия намного сложнее, чем простое изменение UI.

Как бы то ни было, этого всё равно было для нас недостаточно, и мы хотели реализовать совершенно обобщённое решение, поэтому создали библиотеку, реализующую Flux в Unity. Это привело к очень простому решению, при котором всё состояние игры хранится в объекте «Store», а все элементы UI и другие компоненты уведомляются при изменении состояния и реагируют на это изменение без кода в методе Update.

Третье правило: циклы всегда под подозрением
Это точно такое же правило, которое я упоминал в первой части статьи. Если в коде есть какой-то цикл, итеративно обходящий большое количество элементов, то для улучшения производительности цикла используйте оба правила из обеих частей статьи.

Четвёртое правило: For лучше, чем Foreach
Цикл Foreach очень легко написать, но «очень сложно» выполнять. Внутри цикла Foreach используются Enumerator для итеративной обработки набора данных и возврата значения. Это сложнее, чем итерация индексов в простом цикле For.

Поэтому в нашем проекте мы по возможности заменили циклы Foreach на For:

//Bad codeforeach (GameObject obstacle in obstacles)//Better codevar count = obstacles.Count;for (int i = 0; i < count; i++) { obstacles;
}
В нашем случае с большим циклом for это изменение очень значимо. Простой цикл for ускорил код в два раза.

Пятое правило: массивы лучше, чем списки
В своём коде мы выяснили, что большинство списков (List) имеет постоянную длину или мы можем вычислить максимальное количество элементов. Поэтому мы реализовали их заново на основе массивов и в некоторых случаях это привело к двукратному ускорению итераций над данными.

В некоторых случаях избежать списков или других сложных структур данных нельзя. Случается, что приходится часто добавлять или удалять элементы, и в таком случае лучше использовать списки. Но в общем случае для списков фиксированной длины всегда следует использовать массивы.

Шестое правило: операции с Float лучше, чем операции с векторами
Это различие едва заметно, если вы не выполняете тысячи подобных операций, как и было в нашем случае, поэтому для нас увеличение производительности оказалось значимым.

Мы вносили подобные изменения:

Vector3 pos1 = new Vector3(1,2,3);Vector3 pos2 = new Vector3(4,5,6);//Bad codevar pos3 = pos1 + pos2;//Better codevar pos3 = new Vector3(pos1.x + pos2.x, pos1.y + pos2.y, ......);Vector3 pos1 = new Vector3(1,2,3);//Bad codevar pos2 = pos1 * 2f;//Better codevar pos2 = new Vector3(pos1.x * 2f, pos1.y * 2f, ......);
Седьмое правило: искать объекты правильно
Всегда думайте, действительно ли нужно использовать метод GameObject.Find(). Этот метод тяжёл и занимает безумное количество времени. Никогда не следует использовать такой метод в методах Update. Мы выяснили, что большинство наших вызовов Find можно заменить прямыми ссылками в редакторе, что, разумеется, гораздо лучше.

//Bad CodeGameObject player;

void Start(){
player = GameObject.Find("PLAYER");}

//Better Code//Assign the reference to the player object in editor[SerializeField]GameObject player;
void Start(){
}
В случае, если так сделать невозможно, то хотя бы рассмотрите возможность использования меток (Tag) и поиска объекта по его метке при помощи GameObject.FindWithTag.

Итак, в общем случае: Прямая ссылка > GameObject.FindWithTag() > GameObject.Find()

Восьмое правило: работайте только с относящимися к делу объектами
В нашем случае это было важно для распознавания коллизий при помощи RayCast-ов (CircleCast и т.п.). Вместо распознавания коллизий и принятия решения о том, какие из них важны, в коде, мы переместили игровые объекты на соответствующие слои, чтобы можно было вычислять коллизии только для нужных объектов.

Вот пример

//Bad Codevoid DetectCollision(){
var count = Physics2D.CircleCastNonAlloc( position, radius, direction, results, distance);
for (int i = 0; i < count; i++) { var obj = results.collider.transform.gameObject; if(obj.CompareTag("FOO")) { ProcessCollision(results);
}
}
}

//Better Code//We added all objects with tag FOO into the same layervoid DetectCollision(){
//8 is number of the desired layer var mask = 1 << 8; var count = Physics2D.CircleCastNonAlloc( position, radius, direction, results, distance, mask);
for (int i = 0; i < count; i++) { ProcessCollision(results);
}
}
Девятое правило: правильно используйте метки
Нет никаких сомнений, что метки очень полезны и могут улучшить производительность кода, но помните, что существует только один правильный способ сравнения меток объектов!

//Bad CodegameObject.Tag == "MyTag";//Better CodegameObject.CompareTag("MyTag");
Десятое правило: опасайтесь хитростей с камерой!
Так легко использовать Camera.main, но производительность этого действия очень плоха. Причина заключается в том, что за кулисами каждого вызова Camera.main движок Unity на самом деле выполняет для получения результата FindGameObjectsWithTag(), поэтому мы уже понимаем, что часто его вызывать не нужно, и лучше всего решить эту проблему, кешировав ссылку в методе Start или Awake.

//Bad codevoid Update(){
Camera.main.orthographicSize //Some operation with camera}

//Better Codeprivate Camera cam;void Start(){
cam = Camera.main;
}
void Update(){
cam.orthographicSize //Some operation with camera}
Одиннадцатое правило: LocalPosition лучше, чем Position
Везде, где это возможно, используйте для геттеров и сеттеров Transform.LocalPosition вместо Transform.Position. Внутри каждого вызова Transform.Position выполняется гораздо больше операций, например, вычисление глобальной позиции в случае вызова геттера или вычисление локальной позиции из глобальной в случае вызова сеттера. В нашем проекте выяснилось, что можно использовать LocalPositions в 99% случаев использования Transform.Position, и в коде при этом не нужно делать никаких других изменений.

Двенадцатое правило: не использовать LINQ
Об этом уже говорили в первой части. Просто не используйте его, вот и всё.

Тринадцатое правило: не бойтесь (иногда) нарушать правила
Иногда даже вызов простой функции может быть слишком затратным. В этом случае всегда следует рассмотреть возможность встраивания кода (Code Inlining). Что это значит? По сути, мы просто берём код из функции и копируем его непосредственно в место, где хотим использовать функцию, чтобы избежать вызовов дополнительных методов.

В большинстве случаев это не окажет никакого влияния, потому что встраивание кода выполняется автоматически на этапе компиляции, но существуют определённые правила, по которым компилятор решает, должен ли встраиваться код. Поэтому просто откройте профилировщик, запустите игру на целевом устройстве и посмотрите, можно ли что-то улучшить.

В нашем случае нашлось несколько функций, которые мы решили встроить для улучшения производительности, особенно в большом цикле for.

Вывод
Применив перечисленные в статье правила, мы легко добились стабильных 60 fps в игре для iOS даже на iPhone 5S. Возможно, некоторые из правил могут быть специфичными только для нашего проекта, но я считаю, что большинство из них стоит помнить при написании кода или его проверке, чтобы избежать проблем в дальнейшем. Всегда лучше постоянно писать код с учётом производительности, чем позже рефакторить большие фрагменты кода.
►ИДЕАЛЬНЫЙ ИГРОК RMT
Loading… ███████[][][] 70%

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

  • Shpilevoy
  • Shpilevoy аватар Автор темы
  • VIP
  • VIP
  • ∻♥♚ RMT ♚♥∻
  • Сообщений: 5066

Re: Roulette MEGA Tracker (RMT) - калькулятор ставок Шпилевого

11 мес. 3 нед. назад - 11 мес. 3 нед. назад
#30
Shpilevoy пишет: Так. Столкнулся с неожиданной проблемой в редакторе UNITY ...
Нашел хорошую статью по оптимизации проекта..... выполнил только первые два правила...
и ОШИБКА ИСЧЕЗЛА!



Нет, не исчезла!
Еще есть надежда, что это траблы чисто редактора UNITY. Иногда 300 спинов без зависания, а иногда на 30 спин виснет...


Подключил 7 атомов = для игры нормально.... но в планах идти дальше и больше. Что делать?
Выкладывать "как есть" не хочу, еще поборюсь =

1) Посмотрю на телефоне что будет происходить.
2) Запишу контрольную генерацию на которой виснет = если будет повторяемость ошибки в одном месте, то это логика программы. Поочередно включать атомы и тестить по 1000 спинов на зависание.... в каком именно происходит
3) FixedUpdate поменяю на просто Update = вдруг успеет в логи выкинуть текст ошибки на очередном зависании...

//////////////////////

Пока пройдусь по залам, поработаю )))
►ИДЕАЛЬНЫЙ ИГРОК RMT
Loading… ███████[][][] 70%

Вложения:

Спасибо сказали: LUCKY-13, Снежанна

Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.

 

E pluribus unum

 

Sup: admin@casino-mining.com

Copyright © 2011-2024 ESPT GO LIMITED Reg. : HE 370907

Vasili Michailidi, 9, 3026, Limassol, Cyprus, phone: +35796363497

 

Excellent Teamwork