/// <reference types="@rbxts/compiler-types" />
/// <reference types="@rbxts/types" />
/// <reference types="@rbxts/types" />
/// <reference types="@rbxts/compiler-types" />
declare type NetworkParams<T> = Parameters<T extends unknown[] ? (...args: T) => void : T extends void ? () => void : T extends unknown ? (arg: T) => void : () => void>;
declare type NetworkReturn<T> = T extends [infer A] ? A : T;
/**
 * NetEvent type.
 */
export declare enum NetEventType {
    /**
     * NetEvent can send and receive from both the server and the client.
     */
    TwoWay = 0,
    /**
     * NetEvent can send from the server and receive on the client.
     */
    ServerToClient = 1,
    /**
     * NetEvent can send from the client and receive on the server.
     */
    ClientToServer = 2
}
interface INetEventClientFire<T extends unknown[] | unknown> {
    /**
     * Fire the event to the server with the given arguments.
     * @param args Arguments
     */
    fire(...args: NetworkParams<T>): void;
}
interface INetEventClientConnect<T extends unknown[] | unknown> {
    /**
     * Listen to events coming from the server.
     * @param handler Handle the event
     * @returns RBXScriptConnection
     */
    connect(handler: (...args: NetworkParams<T>) => void): RBXScriptConnection;
}
declare type INetEventClient<T extends unknown[] | unknown> = INetEventClientFire<T> & INetEventClientConnect<T>;
declare type NetEventClientExposed<T extends unknown[] | unknown, B extends NetEventType> = INetEventClient<T> & B extends NetEventType.TwoWay ? INetEventClient<T> : B extends NetEventType.ServerToClient ? INetEventClientConnect<T> : INetEventClientFire<T>;
interface INetEventServerFire<T extends unknown[] | unknown> {
    /**
     * Fire the event to the given client(s) with the arguments.
     * @param player Client(s)
     * @param args Arguments
     */
    fire(player: Player | Player[], ...args: NetworkParams<T>): void;
    /**
     * Fire the event to all clients with the given arguments.
     * @param args Arguments
     */
    fireAll(...args: NetworkParams<T>): void;
    /**
     * Fire the event to all clients _except_ the given client(s).
     * @param exceptPlayer Client(s) to ignore
     * @param args Arguments
     */
    fireExcept(exceptPlayer: Player | Player[], ...args: NetworkParams<T>): void;
    /**
     * Fire the event to each client given the predicate for each client returns `true`.
     * @param predicate Predicate function to test if the event should be fired to the given client
     * @param args Arguments
     */
    fireIf(predicate: (player: Player) => boolean, ...args: NetworkParams<T>): void;
}
interface INetEventServerConnect<T extends unknown[] | unknown> {
    /**
     * Listen to events coming from all clients.
     * @param handler Handle the event
     * @returns RBXScriptConnection
     */
    connect(handler: (player: Player, ...args: NetworkParams<T>) => void): RBXScriptConnection;
}
declare type INetEventServer<T extends unknown[] | unknown> = INetEventServerFire<T> & INetEventServerConnect<T>;
declare type NetEventServerExposed<T extends unknown[] | unknown, B extends NetEventType> = INetEventServer<T> & B extends NetEventType.TwoWay ? INetEventServer<T> : B extends NetEventType.ServerToClient ? INetEventServerFire<T> : INetEventServerConnect<T>;
declare class NetFunctionServer<TX extends unknown[] | unknown, RX extends unknown[] | unknown> {
    private readonly rf;
    constructor(rf: RemoteFunction);
    /**
     * Handle invocations to this remote function coming from clients.
     * @param handler Handler
     */
    handle(handler: (player: Player, ...args: NetworkParams<TX>) => NetworkReturn<RX>): void;
}
declare class NetFunctionClient<TX extends unknown[] | unknown, RX extends unknown[] | unknown> {
    private readonly rf;
    constructor(rf: RemoteFunction);
    /**
     * Invoke the remote function, sending the arguments to the server.
     * @param args TX
     * @returns RX
     */
    invoke(...args: NetworkParams<TX>): Promise<NetworkReturn<RX>>;
}
/**
 * NetEvent represents a RemoteEvent.
 *
 * ```ts
 * export const MyEvent = new NetEvent<[message: string]>();
 * ```
 */
export declare class NetEvent<T extends unknown[] | unknown, B extends NetEventType = NetEventType.TwoWay> {
    private readonly re;
    /**
     * Server API for the event. Should only be used from the server.
     */
    readonly server: NetEventServerExposed<T, B>;
    /**
     * Client API for the event. Should only be used from the client.
     */
    readonly client: NetEventClientExposed<T, B>;
    constructor(name?: string);
}
/**
 * NetFunction represents a RemoteFunction.
 *
 * ```ts
 * export const MyFunc = new NetFunction<void, [message: string]>();
 * ```
 */
export declare class NetFunction<TX extends unknown[] | unknown, RX extends unknown[] | unknown> {
    private readonly rf;
    /**
     * Server API for the function. Should only be used from the server.
     */
    readonly server: NetFunctionServer<TX, RX>;
    /**
     * Client API for the function. Should only be used from the client.
     */
    readonly client: NetFunctionClient<TX, RX>;
    constructor(name?: string);
}
export {};
