func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error {
	if s.IsInstalling() {
		return ErrServerIsInstalling
	}
	if s.IsTransferring() {
		return ErrServerIsTransferring
	}
	if s.IsRestoring() {
		return ErrServerIsRestoring
	}
	if s.powerLock == nil {
		s.powerLock = semaphore.NewWeighted(1)
	}
	if action != PowerActionTerminate {
		if len(waitSeconds) > 0 && waitSeconds[0] != 0 {
			ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(waitSeconds[0]))
			defer cancel()
			if err := s.powerLock.Acquire(ctx, 1); err != nil {
				return errors.WithMessage(err, "could not acquire lock on power state")
			}
		} else {
			if ok := s.powerLock.TryAcquire(1); !ok {
				return errors.WithMessage(context.DeadlineExceeded, "could not acquire lock on power state")
			}
		}
		defer s.powerLock.Release(1)
	} else {
		if ok := s.powerLock.TryAcquire(1); ok {
			defer s.powerLock.Release(1)
		}
	}
	switch action {
	case PowerActionStart:
		if s.Environment.State() != environment.ProcessOfflineState {
			return ErrIsRunning
		}
		if err := s.onBeforeStart(); err != nil {
			return err
		}
		return s.Environment.Start(s.Context())
	case PowerActionStop:
		return s.Environment.WaitForStop(10*60, true)
	case PowerActionRestart:
		if err := s.Environment.WaitForStop(10*60, true); err != nil {
			return err
		}
		if err := s.onBeforeStart(); err != nil {
			return err
		}
		return s.Environment.Start(s.Context())
	case PowerActionTerminate:
		return s.Environment.Terminate(os.Kill)
	}
	return errors.New("attempting to handle unknown power action")
}
HandlePowerAction is a helper function that can receive a power action and then process the
actions that need to occur for it. This guards against someone calling Start() twice at the
same time, or trying to restart while another restart process is currently running.

However, the code design for the daemon does depend on the user correctly calling this
function rather than making direct calls to the start/stop/restart functions on the
environment struct.
package server
import (
	"context"
	"os"
	"time"
	"emperror.dev/errors"
	"golang.org/x/sync/semaphore"
	"github.com/pterodactyl/wings/config"
	"github.com/pterodactyl/wings/environment"
)
type PowerAction string
const (
	PowerActionStart     = "start"
	PowerActionStop      = "stop"
	PowerActionRestart   = "restart"
	PowerActionTerminate = "kill"
)
func (pa PowerAction) IsValid() bool {
	return pa == PowerActionStart ||
		pa == PowerActionStop ||
		pa == PowerActionTerminate ||
		pa == PowerActionRestart
}
func (pa PowerAction) IsStart() bool {
	return pa == PowerActionStart || pa == PowerActionRestart
}
func (s *Server) ExecutingPowerAction() bool {
	if s.powerLock == nil {
		return false
	}
	ok := s.powerLock.TryAcquire(1)
	if ok {
		s.powerLock.Release(1)
	}
	return !ok
}