MasterGH Опубликовано 4 марта, 2015 Поделиться Опубликовано 4 марта, 2015 Общие понятия Авторитарный сервер (или мастер сервер)На этом сервере хранятся все данные или наиболее важные данные и логика игры. Клиенты просят сервер что-то сделать, сервер пропускает через функции, условия игры и выдает ответ отвечающему или еще и на другие клиенты.КлиентНа клиенте как правило хранятся данные копии. В зависимости от игры расчеты могут быть и на клиенте, чтобы снять нагрузку на цпу сервера и разгрузить траффик. Как правило расчеты физики, столкновений в сетевых играх стараются либо избежать, либо отводят на клиент или мастер клиент.Мастер-клиентМастер клиент как правило, тот кто создает комнату, игру, лобби. Снимает всю или бОльшую часть нагрузки на серверную сторону. Мастер клиент берет полный или частичный контроль над игрой. А серверная сторона либо передает тупо пакеты между мастер-клиентами и клиентами, либо серверная сторона еще и контролирует как-то игру. Связи Авторитарный + клиентыАвторитарный сервер принимает "вопросы и предложения от клиентов" в течении игры. Реагирует на них и отправляет результаты тому кто спрашивал или еще и тем кто в игре.Не авторитарный + мастер клиент + клиентыИгрок, который создал игру примает "вопросы и предложения от клиентов" в течении игры. Реагирует на них и отправляет результаты тому кто спрашивал или еще и тем кто в игре. Т.е. мастер клиент хранит данные, все что происходит в игре синхронизируется с ним. Не авторитарный сервер выступает в качестве посредника рассылки пакетов между игроками минуя NAT.Частично автоританый + мастер клиент + клиентыАвторитарный сервер может влиять на игру между мастер клиентом и клиентами. Чем это влияние сильнее, тем больше ограничений в сетевой игре получается. Например. Сервер ведет счет времени на игру между клиентами и мастер клиентами. Если у кого-то так называемая "энергия" закончилась, то сервер, говорит, что Вам нельзя начать новую игру. Пример игры Трагедия Белок. Но я не уверен, что там есть мастер клиент. Возможно там полный контроль авторитарного сервера, т.е. физика и движения рассчитаются не мастер клиентом, а сервером. Пример того как выглядят система Клиент + Частично авторитарный сервер Игра-пример с yahoogames про игру поиск грибов игроками в темноте. Частично авторитарный сервер создает грибы в темноте по интервалу времени. В этом всего лишь и заключается авторитарность. Сервер только создает грибы, когда посчитает нужным. Взятие грибов серверная сторона НЕ КОТРОЛИРУЕТ. В общем этот пример для тех, кто хочет задуматься. Роль сервера и роль клиентов очень гибкая и в задачу разработчика входит много проблем, чтобы не допустить читов. Если разраб ничего делать не будет, будет чит на чите. Разраб преследует концепцию "никогда не доверять клиентам" Показать контент Клиентская сторона: Показать контент Серверная сторона Показать контент Полный проект можно скачать:Yahoo Games Network SDK.zipДокументация: ссылка//-----------------------------------------------------------------------------------------------------------------// // Mushroom Example// Created by : Luis Filipe (filipe@seines.pt)// Dec 2010//// Source code in this example is in the public domain.// The naruto character model in this demo is copyrighted by Ben Mathis.// See Assets/Models/naruto.txt for more details////-----------------------------------------------------------------------------------------------------------------using UnityEngine;using System.Collections;using System.Collections.Generic;using PlayerIOClient;public class ChatEntry { public string text = ""; public bool mine = true;}public class GameManager : MonoBehaviour { public GameObject target; public GameObject PlayerPrefab; public GameObject ToadPrefab; private Connection pioconnection; private List<PlayerIOClient.Message> msgList = new List<PlayerIOClient.Message>(); // Messsage queue implementation private bool joinedroom = false; // UI stuff private Vector2 scrollPosition; private ArrayList entries = new ArrayList(); private string inputField = ""; private Rect window = new Rect(10, 10, 300, 150); private int toadspicked = 0; private string infomsg = ""; void Start() { // create a random userid System.Random random = new System.Random(); string userid = "Guest" + random.Next(0, 10000); Debug.Log("Starting"); PlayerIOClient.PlayerIO.Connect( "[Enter your game id here]", // Game id (Get your own at playerio.com. 1: Create user, 2:Goto admin pannel, 3:Create game, 4: Copy game id inside the "") "public", // The id of the connection, as given in the settings section of the admin panel. By default, a connection with id='public' is created on all games. userid, // The id of the user connecting. This can be any string you like. For instance, it might be "fb10239" if youґre building a Facebook app and the user connecting has id 10239 null, // If the connection identified by the connection id only accepts authenticated requests, the auth value generated based on UserId is added here null, null, delegate(Client client) { Debug.Log("Successfully connected to Player.IO"); infomsg = "Successfully connected to Player.IO"; target.transform.Find("NameTag").GetComponent<TextMesh>().text = userid; target.transform.name = userid; // Uncoment the line below to use the Development Server client.Multiplayer.DevelopmentServer = new ServerEndpoint("localhost",8184); //Create or join the room client.Multiplayer.CreateJoinRoom( "UnityDemoRoom", //Room id. If set to null a random roomid is used "UnityMushrooms", //The room type started on the server true, //Should the room be visible in the lobby? null, null, delegate(Connection connection) { Debug.Log("Joined Room."); infomsg = "Joined Room."; // We successfully joined a room so set up the message handler pioconnection = connection; pioconnection.OnMessage += handlemessage; joinedroom = true; }, delegate(PlayerIOError error) { Debug.Log("Error Joining Room: " + error.ToString()); infomsg = error.ToString(); } ); }, delegate(PlayerIOError error) { Debug.Log("Error connecting: " + error.ToString()); infomsg = error.ToString(); } ); } void handlemessage(object sender, PlayerIOClient.Message m) { msgList.Add(m); } void FixedUpdate() { // process message queue foreach(PlayerIOClient.Message m in msgList) { switch(m.Type) { case "PlayerJoined": GameObject newplayer = GameObject.Instantiate(target) as GameObject; newplayer.transform.position = new Vector3(m.GetFloat(1), 0, m.GetFloat(2)); newplayer.name = m.GetString(0); newplayer.transform.Find("NameTag").GetComponent<TextMesh>().text = m.GetString(0); break; case "Move": GameObject upplayer = GameObject.Find(m.GetString(0)); upplayer.transform.LookAt(new Vector3(m.GetFloat(1), 0, m.GetFloat(2))); // set transform x axis to 0, so the character will be facing forward upplayer.transform.eulerAngles = new Vector3(0, upplayer.transform.eulerAngles.y, upplayer.transform.eulerAngles.z); // get distance between current position and target position, // we'll need to value to know how much the tween will last float dist = Vector3.Distance(upplayer.transform.position, new Vector3(m.GetFloat(1), 0, m.GetFloat(2))); // create a tween between current and target position iTween.MoveTo(upplayer, iTween.Hash("x", m.GetFloat(1), "z", m.GetFloat(2), "onstart", "startwalk", "oncomplete", "stopwalk", "time", dist, "delay", 0, "easetype", iTween.EaseType.linear)); break; case "Harvest": GameObject hvplayer = GameObject.Find(m.GetString(0)); hvplayer.transform.LookAt(new Vector3(m.GetFloat(1), .5f, m.GetFloat(2))); // set transform x axis to 0, so the character will be facing forward hvplayer.transform.eulerAngles = new Vector3(0, hvplayer.transform.eulerAngles.y, hvplayer.transform.eulerAngles.z); // get distance between current position and target position, // we'll need to value to know how much the tween will last float distance = Vector3.Distance(hvplayer.transform.position, new Vector3(m.GetFloat(1), 0, m.GetFloat(2))); // create a tween between current and target position iTween.MoveTo(hvplayer, iTween.Hash("x", m.GetFloat(1), "z", m.GetFloat(2), "onstart", "startwalk", "oncomplete", "stopharvest", "time", distance, "delay", 0, "easetype", iTween.EaseType.linear)); break; case "Picked": // remove the object when it's picked up GameObject removetoad = GameObject.Find("Toad" + m.GetInt(0)); Destroy(removetoad); break; case "Chat": if(m.GetString(0) != "Server") { GameObject chatplayer = GameObject.Find(m.GetString(0)); chatplayer.transform.Find("Chat").GetComponent<TextMesh>().text = m.GetString(1); chatplayer.transform.Find("Chat").GetComponent<MeshRenderer>().material.color = Color.white; chatplayer.transform.Find("Chat").GetComponent<chatclear>().lastupdate = Time.time; } ChatText(m.GetString(0) + " says: " + m.GetString(1), false); break; case "PlayerLeft": // remove characters from the scene when they leave GameObject playerd = GameObject.Find(m.GetString(0)); Destroy(playerd); break; case "Toad": // adds a toadstool to the scene GameObject newtoad = GameObject.Instantiate(ToadPrefab) as GameObject; newtoad.transform.position = new Vector3(m.GetFloat(1), 0.1f, m.GetFloat(2)); newtoad.name = "Toad" + m.GetInt(0); break; case "ToadCount": // updates how many toads have been picked up by the player toadspicked = m.GetInt(0); break; } } // clear message queue after it's been processed msgList.Clear(); } void OnMouseDown() { // this function responds to mouse clicks on the ground // it will send a move request to the server // ignore user input if we're not inside a room if(!joinedroom) return; Vector3 targetPosition = new Vector3(0, 0, 0); var playerPlane = new Plane(Vector3.up, target.transform.position); var ray = Camera.main.ScreenPointToRay(Input.mousePosition); var hitdist = 0.0f; if(playerPlane.Raycast(ray, out hitdist)) { targetPosition = ray.GetPoint(hitdist); pioconnection.Send("Move", targetPosition.x, targetPosition.z); } } void OnGUI() { window = GUI.Window(1, window, GlobalChatWindow, "Chat"); GUI.Label(new Rect(10, 160, 150, 20), "Toadstools picked: " + toadspicked); if(infomsg != "") { GUI.Label(new Rect(10, 180, Screen.width, 20), infomsg); } } public void HarvestAt(float posx, float posz) { pioconnection.Send("MoveHarvest", posx, posz); } public void TryPickup(string id) { pioconnection.Send("Pickup", id); } void GlobalChatWindow(int id) { if(!joinedroom) return; GUI.FocusControl("Chat input field"); // Begin a scroll view. All rects are calculated automatically - // it will use up any available screen space and make sure contents flow correctly. // This is kept small with the last two parameters to force scrollbars to appear. scrollPosition = GUILayout.BeginScrollView(scrollPosition); foreach(ChatEntry entry in entries) { GUILayout.BeginHorizontal(); if(!entry.mine) { GUILayout.Label(entry.text); } else { GUI.contentColor = Color.yellow; GUILayout.Label(entry.text); GUI.contentColor = Color.white; } GUILayout.EndHorizontal(); GUILayout.Space(3); } // End the scrollview we began above. GUILayout.EndScrollView(); if(Event.current.type == EventType.keyDown && Event.current.keyCode == KeyCode.Return && inputField.Length > 0) { GameObject chatplayer = GameObject.Find(target.transform.name); chatplayer.transform.Find("Chat").GetComponent<TextMesh>().text = inputField; chatplayer.transform.Find("Chat").GetComponent<MeshRenderer>().material.color = Color.white; chatplayer.transform.Find("Chat").GetComponent<chatclear>().lastupdate = Time.time; ChatText(target.transform.name + " says: " + inputField, true); pioconnection.Send("Chat", inputField); inputField = ""; } GUI.SetNextControlName("Chat input field"); inputField = GUILayout.TextField(inputField); GUI.DragWindow(); } void ChatText(string str, bool own) { var entry = new ChatEntry(); entry.text = str; entry.mine = own; entries.Add(entry); if(entries.Count > 50) entries.RemoveAt(0); scrollPosition.y = 1000000; }}using System;using System.Collections.Generic;using System.Text;using System.Collections;using PlayerIO.GameLibrary;using System.Drawing;namespace MushroomsUnity3DExample { public class Player : BasePlayer { public float posx = 0; public float posz = 0; public int toadspicked = 0; } public class Toad { public int id = 0; public float posx = 0; public float posz = 0; } [RoomType("UnityMushrooms")] public class GameCode : Game<Player> { private int last_toad_id = 0; private List<Toad> Toads = new List<Toad>(); // This method is called when an instance of your the game is created public override void GameStarted() { // anything you write to the Console will show up in the // output window of the development server Console.WriteLine("Game is started: " + RoomId); // spawn 10 toads at server start System.Random random = new System.Random(); for(int x = 0; x < 10; x++) { int px = random.Next(-9, 9); int pz = random.Next(-9, 9); Toad temp = new Toad(); temp.id = last_toad_id; temp.posx = px; temp.posz = pz; Toads.Add(temp); last_toad_id++; } // respawn new toads each 5 seconds AddTimer(respawntoads, 5000); // reset game every 2 minutes AddTimer(resetgame, 120000); } private void resetgame() { // scoring system Player winner = new Player(); int maxscore = -1; foreach(Player pl in Players) { if(pl.toadspicked > maxscore) { winner = pl; maxscore = pl.toadspicked; } } // broadcast who won the round if(winner.toadspicked > 0) { Broadcast("Chat", "Server", winner.ConnectUserId + " picked " + winner.toadspicked + " Toadstools and won this round."); } else { Broadcast("Chat", "Server", "No one won this round."); } // reset everyone's score foreach(Player pl in Players) { pl.toadspicked = 0; } Broadcast("ToadCount", 0); } private void respawntoads() { if(Toads.Count == 10) return; System.Random random = new System.Random(); // create new toads if there are less than 10 for(int x = 0; x < 10 - Toads.Count; x++) { int px = random.Next(-9, 9); int pz = random.Next(-9, 9); Toad temp = new Toad(); temp.id = last_toad_id; temp.posx = px; temp.posz = pz; Toads.Add(temp); last_toad_id++; // broadcast new toad information to all players Broadcast("Toad", temp.id, temp.posx, temp.posz); } } // This method is called when the last player leaves the room, and it's closed down. public override void GameClosed() { Console.WriteLine("RoomId: " + RoomId); } // This method is called whenever a player joins the game public override void UserJoined(Player player) { foreach(Player pl in Players) { if(pl.ConnectUserId != player.ConnectUserId) { pl.Send("PlayerJoined", player.ConnectUserId, 0, 0); player.Send("PlayerJoined", pl.ConnectUserId, pl.posx, pl.posz); } } // send current toadstool info to the player foreach(Toad t in Toads) { player.Send("Toad", t.id, t.posx, t.posz); } } // This method is called when a player leaves the game public override void UserLeft(Player player) { Broadcast("PlayerLeft", player.ConnectUserId); } // This method is called when a player sends a message into the server code public override void GotMessage(Player player, Message message) { switch(message.Type) { // called when a player clicks on the ground case "Move": player.posx = message.GetFloat(0); player.posz = message.GetFloat(1); Broadcast("Move", player.ConnectUserId, player.posx, player.posz); break; case "MoveHarvest": // called when a player clicks on a harvesting node // sends back a harvesting command to the player, a move command to everyone else player.posx = message.GetFloat(0); player.posz = message.GetFloat(1); foreach(Player pl in Players) { if(pl.ConnectUserId != player.ConnectUserId) { pl.Send("Move", player.ConnectUserId, player.posx, player.posz); } } player.Send("Harvest", player.ConnectUserId, player.posx, player.posz); break; case "Pickup": // called when the player is actually close to the harvesting node int pickupid = int.Parse(message.GetString(0).Replace("Toad", "")); // Find a toad by its id Toad result = Toads.Find( delegate(Toad td) { return td.id == pickupid; } ); if(result != null) { // sends everyone information that a toad as been picked up // increases player toad count Broadcast("Picked", result.id); Toads.Remove(result); player.toadspicked++; player.Send("ToadCount", player.toadspicked); } else { // id of the toad doesn't exist, either the player // is trying to cheat, or someone else already picked // that toadstool Console.WriteLine("Not found: {0}", pickupid); } break; case "Chat": foreach(Player pl in Players) { if(pl.ConnectUserId != player.ConnectUserId) { pl.Send("Chat", player.ConnectUserId, message.GetString(0)); } } break; } } }} Ссылка на комментарий Поделиться на другие сайты Поделиться
krocki Опубликовано 6 марта, 2015 Поделиться Опубликовано 6 марта, 2015 Ухты! Очень интересно... Думаю без атаки на сервак...сложно/нереально будет что-то сделать...всё-же спасибо MasterGH Кстати тут такой прикол вышел у меня...заранее прошу прощения если что. Играл в CS1.6_UCP_8.3 в окне 640x480...решил тупо открыть Cheat Engine и тут синий экран смерти... Ладно! перезагрузил комп...открыл сначала Cheat Engine, а потом запустил контру и бах опять экран смерти. Признаюсь! даже не пытался что то там хакнуть в контре, а тупо открыл скрипт от другой игры просто хотел поправить скрипт который делал для Residen Evil: Revelation 2, а тут такое. Походу UСP сделала такую защиту, что даже запустив прогу Cheat Engine...и приходит конец всему сразу. Дааа-уж!!! Нет слов. NullAlex: красный цвет может использовать только администрация. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 6 марта, 2015 Поделиться Опубликовано 6 марта, 2015 В 06.03.2015 в 13:46, krocki сказал: Ухты! Очень интересно... Думаю без атаки на сервак...сложно/нереально будет что-то сделать...всё-же спасибо MasterGH Кстати тут такой прикол вышел у меня...заранее прошу прощения если что. Играл в CS1.6_UCP_8.3 в окне 640x480...решил тупо открыть Cheat Engine и тут синий экран смерти... Ладно! перезагрузил комп...открыл сначала Cheat Engine, а потом запустил контру и бах опять экран смерти. Признаюсь! даже не пытался что то там хакнуть в контре, а тупо открыл скрипт от другой игры просто хотел поправить скрипт который делал для Residen Evil: Revelation 2, а тут такое. Походу UСP сделала такую защиту, что даже запустив прогу Cheat Engine...и приходит конец всему сразу. Дааа-уж!!! Нет слов.1. Ddos решает 2. Бсодит? Ну незнаю... Мб проблема в той табличке, которую ты открывал? Ссылка на комментарий Поделиться на другие сайты Поделиться
krocki Опубликовано 6 марта, 2015 Поделиться Опубликовано 6 марта, 2015 RockHamer Не совсем я тебя понял что ты имел ввиду.По отдельности запускаешь всё нормально CE или контру, всё работает...UCP походу видит процесс CE и сразу вылетает синий экран смерти "BSOD".Ладно бы просто ошибку выдавал, но нет...сразу конец всему.На другом компе проверил...тоже самое.6-7 раз комп свой перезагружал для полной достоверности.Даже старая версия CE 5.5_5.6, такой-же результат даёт "BSOD" и всё. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 6 марта, 2015 Поделиться Опубликовано 6 марта, 2015 (изменено) В 06.03.2015 в 18:06, krocki сказал: RockHamer Не совсем я тебя понял что ты имел ввиду.По отдельности запускаешь всё нормально CE или контру, всё работает...UCP походу видит процесс CE и сразу вылетает синий экран смерти "BSOD".Ладно бы просто ошибку выдавал, но нет...сразу конец всему.На другом компе проверил...тоже самое.6-7 раз комп свой перезагружал для полной достоверности.Даже старая версия CE 5.5_5.6, такой-же результат даёт "BSOD" и всё.Скорее всего критическая ошибка в UCP. Инфа соточка, т.к. СЕ со всеми дружит и не конфликтует. Надо бы разрабам этого "чуда" отрапортавать. В 04.03.2015 в 01:18, MasterGH сказал: Авторитарный сервер (или мастер сервер)Я прочитал - тоталитарный )) Отличник по истории)) Изменено 6 марта, 2015 пользователем RockHamer Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 6 марта, 2015 Поделиться Опубликовано 6 марта, 2015 Если в настройках CE выбран отладчик с DBVM - синий экран вполне возможен. Ссылка на комментарий Поделиться на другие сайты Поделиться
ARM4ND0 Опубликовано 6 марта, 2015 Поделиться Опубликовано 6 марта, 2015 Попробуй сбросить настройки СЕ(ceregreset.exe). Ссылка на комментарий Поделиться на другие сайты Поделиться
krocki Опубликовано 6 марта, 2015 Поделиться Опубликовано 6 марта, 2015 Причём здесь настройки, если я просто запускаю/открываю CE невыбирая процесс игры даже...просто тупо открыть программу CE.при этом у меня сходу экран смерти, если у меня запущена CS1.6_UCP 8.3 не важно где в меню или в самой игре.Сбрасывал настройки и выбирал другой отладчик...всё ровно экран смерти выдаёт.Видимо это защита от CE такая, типа экран смерти. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 7 марта, 2015 Поделиться Опубликовано 7 марта, 2015 (изменено) В 06.03.2015 в 20:27, krocki сказал: Причём здесь настройки, если я просто запускаю/открываю CE невыбирая процесс игры даже...просто тупо открыть программу CE.при этом у меня сходу экран смерти, если у меня запущена CS1.6_UCP 8.3 не важно где в меню или в самой игре.Сбрасывал настройки и выбирал другой отладчик...всё ровно экран смерти выдаёт.Видимо это защита от CE такая, типа экран смерти.Попробуй снести СЕ и поставить заново, на другой диск. И в такой конфигурации (стартовой) попробуй еще раз. Изменено 7 марта, 2015 пользователем RockHamer Ссылка на комментарий Поделиться на другие сайты Поделиться
krocki Опубликовано 7 марта, 2015 Поделиться Опубликовано 7 марта, 2015 Уже пробовал...даже на другом компе проверял...результат тот-же. Если неверите можете сами попробовать, если у вас есть контра с ucp v8.3.Ладно...посути я не пытаюсь и не пытался взломать эту контру...просто стакой фигнёй случайно столкнулся в первые, вот и решил расказать, если кому интересно. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 7 марта, 2015 Поделиться Опубликовано 7 марта, 2015 Отставить панику, это просто один из криво реализованных отладочных приемов. Многие игры тем или иным способом отказываются работать, если находят запущенные сканеры памяти, отладчики, дизассемблеры и прочие подобные утилиты. Просто в этой, видимо, защита реализована в виде обращения к нулевому указателю (что вызывает гарантированный отказ ядра). От подобных штук существуют плагины, в том числе и для Cheat Engine. От большинства подобных штук хорошо помогает kernelmode-отладчик (тот самый, которому нужна DBVM), но он довольно плохо работает (не у всех). Ссылка на комментарий Поделиться на другие сайты Поделиться
krocki Опубликовано 7 марта, 2015 Поделиться Опубликовано 7 марта, 2015 Ну так я и понял что это и происходит.Походу UCP сканирует все запущенные процессы в винде и если обнаружевает сканер памяти,ну или что-то подобное для взлома игр, даёт сразу экран смерти "BSOD"Ладно...как говорится, не проверишь, не узнаешь. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения