Вы можете общаться с исходным потоком через класс, такой как
class Communicator
{
public static volatile bool CreatePlayer;
}
А в коде сокета измените переменную CreatePlayer. В коде получателя проверьте переменную и создайте плеер. После этого установите CreatePlayer в false. Точно так же и с другими вещами. Будьте осторожны при манипулировании одной переменной в двух потоках одновременно - например, может быть лучше иметь четыре логических значения для CreatePlayer, чем иметь int NumPlayersToCreate, чтобы оба потока не пытались постоянно обращаться к одним и тем же данным. Конечно, вам придется профилировать и посмотреть. И последнее: убедитесь, что переменные, измененные в обоих потоках, помечены как изменчивые. Это позволяет каждому потоку обращаться к данным из основной памяти, а не хранить их в кэше (в противном случае каждый поток не заметит, что данные были изменены в кэше другого потока).
Да, это не самое эффективное и элегантное решение, но оно самое простое. Я уверен, что кто-то предложит что-то более сложное; если хочешь, я тоже могу это сделать. Тем не менее, вы, кажется, не знакомы с многопоточностью, поэтому я подумал, что вы захотите начать с чего-то простого.