func NewNetworkFrontend(conn net.Conn) *NetworkFrontend {
	n := NetworkFrontend{
		Network: Network{
			conn:    conn,
			dir:     events.DirFront,
			decoder: json.NewDecoder(conn),
			eventCh: make(chan events.Event),
			close:   make(chan struct{}),
		},
	}
	n.afterDestroy = n.sendLeave
	id, err := uuid.NewV4()
	if err != nil {
		log.Fatalln(err)
	}
	n.id = id.String()
	events.AddListener(n.eventCh, events.DirFront, 0)
	setEvent := &events.SetUUID{
		UUID: n.id,
	}
	n.sendEvent(setEvent)
	go n.readloop()
	go n.mainloop()
	joinEvent := &events.PlayerJoin{
		UUID: n.id,
	}
	events.SendEvent(events.ReloadLevel{})
	events.SendEvent(joinEvent)
	return &n
}
func newBackEnd() *BackEnd {
	b := &BackEnd{
		nextID:   1,
		unitInfo: []*unit{},
		players:  map[string]int{},
		inChn:    make(chan events.Event),
	}
	events.AddListener(b.inChn, events.DirSystem, 0)
	go b.backendLoop()
	return b
}
func NewUnit(x, y float64, w, h int32, id int) *Unit {
	u := &Unit{
		id,
		x, y, w, h,
		make(chan events.Event),
		make(chan Drawable),
		make(chan struct{}),
	}
	events.AddListener(u.eventCh, events.DirFront, u.id)
	go u.mainloop()
	return u
}
func NewUnit(x, y float64, typ *unitType, id int, b *BackEnd) *unit {
	u := &unit{
		id,
		x, y,
		0, 0, 0, 0,
		typ,
		b,
		make(chan events.Event),
		make(chan struct{}),
	}
	events.AddListener(u.eventCh, events.DirSystem, u.unitID)
	go u.unitloop()
	return u
}
func NewPlayerFrontend(win *graphics.Window) *PlayerFrontend {
	p := PlayerFrontend{
		window:  win,
		units:   []*graphics.Unit{},
		inputs:  []InputSystem{ExitInput{}, &KeyboardInput{}},
		eventCh: make(chan events.Event),
		close:   make(chan struct{}),
	}
	id, err := uuid.NewV4()
	if err != nil {
		log.Fatalln(err)
	}
	p.id = id.String()
	events.AddListener(p.eventCh, events.DirFront, 0)
	return &p
}
func NewNetworkBackend(address string) *NetworkBackend {
	n := NetworkBackend{
		Network: Network{
			dir:          events.DirSystem,
			eventCh:      make(chan events.Event),
			close:        make(chan struct{}),
			afterDestroy: nothing,
		},
	}
	conn, err := net.Dial("tcp", net.JoinHostPort(address, port))
	if err != nil {
		log.Fatalln(err)
	}
	n.conn = conn
	n.decoder = json.NewDecoder(n.conn)
	events.AddListener(n.eventCh, events.DirSystem, 0)
	go n.readloop()
	go n.mainloop()
	return &n
}