Skip to content

Commit

Permalink
Merge branch 'master' into release-config
Browse files Browse the repository at this point in the history
  • Loading branch information
TheApplePieGod committed Jan 24, 2024
2 parents a300a53 + 9ad5dd1 commit 2472926
Show file tree
Hide file tree
Showing 31 changed files with 180 additions and 53 deletions.
11 changes: 11 additions & 0 deletions client/src/components/forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,21 @@ export const NumInput: React.FC<NumInputProps> = (props) => {
handleInputChange(tempValue || '')
}

/*
* TODO: these useEffects() are a little mid, they should really store the disabled state
* and restore it instead of absolutely setting it to false
*/

React.useEffect(() => {
context.setState((prevState) => ({ ...prevState, disableHotkeys: focused }))
}, [focused])

React.useEffect(() => {
return () => {
context.setState((prevState) => ({ ...prevState, disableHotkeys: false }))
}
}, [])

return (
<input
className={'border border-black py-0.5 px-1 rounded-md w-12 ' + (props.className ?? '')}
Expand Down
42 changes: 32 additions & 10 deletions client/src/components/sidebar/game/game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { BiMedal } from 'react-icons/bi'
import { EventType, useListenEvent } from '../../../app-events'
import Tooltip from '../../tooltip'
import { useForceUpdate } from '../../../util/react-util'
import Match from '../../../playback/Match'
import { Team } from '../../../playback/Game'

const NO_GAME_TEAM_NAME = '?????'

Expand All @@ -28,25 +30,45 @@ export const GamePage: React.FC<Props> = React.memo((props) => {

if (!props.open) return null

const getWinCount = (team: Team) => {
// Only return up to the current match if tournament mode is enabled
if (!activeGame) return 0
let stopCounting = false
const isWinner = (match: Match) => {
if (context.state.tournament && stopCounting) return 0
if (match == activeGame.currentMatch) stopCounting = true
return match.winner?.id === team.id ? 1 : 0
}
return activeGame.matches.reduce((val, match) => val + isWinner(match), 0)
}

const teamBox = (teamIdx: number) => {
let showMatchWinner =
!context.state.tournament || (context.state.activeMatch && context.state.activeMatch.currentTurn.isEnd())
const winCount = activeGame ? getWinCount(activeGame.teams[teamIdx]) : 0
const isEndOfMatch = context.state.activeMatch && context.state.activeMatch.currentTurn.isEnd()

let showMatchWinner = !context.state.tournament || isEndOfMatch
showMatchWinner = showMatchWinner && activeGame && activeGame.currentMatch?.winner === activeGame.teams[teamIdx]
let showGameWinner =
!context.state.tournament ||
(showMatchWinner &&
context.state.activeMatch ==
context.state.activeGame?.matches[context.state.activeGame.matches.length - 1])
let showGameWinner = !context.state.tournament || (showMatchWinner && winCount >= 3)
showGameWinner = showGameWinner && activeGame && activeGame.winner === activeGame.teams[teamIdx]

return (
<div className={'relative w-full py-2 px-3 text-center ' + (teamIdx == 0 ? 'bg-team0' : 'bg-team1')}>
<div>{activeGame?.teams[teamIdx].name ?? NO_GAME_TEAM_NAME}</div>
<div className="absolute top-2 left-3">
{showMatchWinner && (
<Tooltip text={'Current match winner'} location={'right'}>
<BiMedal fontSize={'24px'} width={'20px'} color={'yellow'} />
</Tooltip>
<div className="relative flex items-center w-[24px] h-[24px]">
<div className="absolute">
<Tooltip text={'Current match winner'} location={'right'}>
<BiMedal opacity={0.5} fontSize={'24px'} width={'20px'} color={'yellow'} />
</Tooltip>
</div>
<div
className="absolute w-full text-sm pointer-events-none z-5"
style={{ textShadow: 'white 0px 0px 4px' }}
>
{winCount > 0 && winCount}
</div>
</div>
)}
</div>
<div className="absolute top-3 right-3">
Expand Down
18 changes: 9 additions & 9 deletions client/src/components/sidebar/game/team-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,20 @@ export const UnitsTable: React.FC<UnitsTableProps> = ({ teamStat, teamIdx }) =>
}

const GlobalUpgradeSection: React.FC<{ teamStat: TeamTurnStat | undefined }> = ({ teamStat }) => {
const upgradeTypes: [schema.GlobalUpgradeType, string][] = [
[schema.GlobalUpgradeType.ACTION_UPGRADE, 'Global Attack Upgrade'],
[schema.GlobalUpgradeType.CAPTURING_UPGRADE, 'Global Capturing Upgrade'],
[schema.GlobalUpgradeType.HEALING_UPGRADE, 'Global Healing Upgrade']
]
const upgradeTypes: Record<schema.GlobalUpgradeType, string> = {
[schema.GlobalUpgradeType.ACTION_UPGRADE]: 'Global Attack Upgrade',
[schema.GlobalUpgradeType.CAPTURING_UPGRADE]: 'Global Capturing Upgrade',
[schema.GlobalUpgradeType.HEALING_UPGRADE]: 'Global Healing Upgrade'
}
if (!teamStat) return <> </>
return (
<>
{upgradeTypes.map(
([type, name]) =>
teamStat.globalUpgrades.has(type) && (
{teamStat.globalUpgrades.map(
(type) =>
upgradeTypes[type] && (
<div className="text-sm flex flex-row justify-center font-bold" key={type}>
<DoubleChevronUpIcon />
{name}
{upgradeTypes[type]}
</div>
)
)}
Expand Down
15 changes: 8 additions & 7 deletions client/src/components/sidebar/runner/runner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { SectionHeader } from '../../section-header'
import { FixedSizeList, ListOnScrollProps } from 'react-window'
import { OpenExternal } from '../../../icons/open-external'
import { BasicDialog } from '../../basic-dialog'
import { RingBuffer } from '../../../util/ring-buffer'

type RunnerPageProps = {
open: boolean
Expand Down Expand Up @@ -67,7 +68,7 @@ export const RunnerPage: React.FC<RunnerPageProps> = ({ open, scaffold }) => {
if (availablePlayers.size > 1) setTeamB([...availablePlayers][1])
}, [availablePlayers])

const MemoConsole = React.useMemo(() => <Console lines={consoleLines} />, [consoleLines])
const MemoConsole = React.useMemo(() => <Console lines={consoleLines} />, [consoleLines.effectiveLength()])

if (!open) return null

Expand Down Expand Up @@ -299,7 +300,7 @@ const JavaSelector: React.FC<JavaSelectorProps> = (props) => {
export type ConsoleLine = { content: string; type: 'output' | 'error' | 'bold' }

type Props = {
lines: ConsoleLine[]
lines: RingBuffer<ConsoleLine>
}

export const Console: React.FC<Props> = ({ lines }) => {
Expand All @@ -320,8 +321,8 @@ export const Console: React.FC<Props> = ({ lines }) => {
}

const ConsoleRow = (props: { index: number; style: any }) => (
<span style={props.style} className={getLineClass(lines[props.index]) + ' text-xs whitespace-nowrap'}>
{lines[props.index].content}
<span style={props.style} className={getLineClass(lines.get(props.index)!) + ' text-xs whitespace-nowrap'}>
{lines.get(props.index)!.content}
</span>
)

Expand All @@ -345,17 +346,17 @@ export const Console: React.FC<Props> = ({ lines }) => {
}

useEffect(() => {
if (lines.length == 0) setTail(true)
if (lines.effectiveLength() == 0) setTail(true)
if (tail && consoleRef.current) {
scrollToBottom()
}
}, [lines])
}, [lines.effectiveLength()])

const lineList = (
<FixedSizeList
outerRef={consoleRef}
height={2000}
itemCount={lines.length}
itemCount={lines.length()}
itemSize={20}
layout="vertical"
width={'100%'}
Expand Down
18 changes: 11 additions & 7 deletions client/src/components/sidebar/runner/scaffold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import WebSocketListener from './websocket'
import { useAppContext } from '../../../app-context'
import Game from '../../../playback/Game'
import Match from '../../../playback/Match'
import { RingBuffer } from '../../../util/ring-buffer'

export type JavaInstall = {
display: string
Expand All @@ -23,7 +24,7 @@ type Scaffold = [
scaffoldLoading: boolean,
runMatch: (javaPath: string, teamA: string, teamB: string, selectedMaps: Set<string>) => Promise<void>,
killMatch: (() => Promise<void>) | undefined,
console: ConsoleLine[]
console: RingBuffer<ConsoleLine>
]

export function useScaffold(): Scaffold {
Expand All @@ -35,12 +36,15 @@ export function useScaffold(): Scaffold {
const [scaffoldPath, setScaffoldPath] = useState<string | undefined>(undefined)
const matchPID = useRef<string | undefined>(undefined)
const forceUpdate = useForceUpdate()
const [consoleLines, setConsoleLines] = useState<ConsoleLine[]>([])
const log = (line: ConsoleLine) =>
setConsoleLines((prev) => (prev.length > 10000 ? [...prev.slice(1), line] : [...prev, line]))
const consoleLines = useRef<RingBuffer<ConsoleLine>>(new RingBuffer(10000))

const [webSocketListener, setWebSocketListener] = useState<WebSocketListener | undefined>()

const log = (line: ConsoleLine) => {
consoleLines.current.push(line)
forceUpdate()
}

async function manuallySetupScaffold() {
if (!nativeAPI) return
setLoading(true)
Expand All @@ -52,6 +56,7 @@ export function useScaffold(): Scaffold {
async function runMatch(javaPath: string, teamA: string, teamB: string, selectedMaps: Set<string>): Promise<void> {
if (matchPID.current || !scaffoldPath) return
const shouldProfile = false
consoleLines.current.clear()
try {
const newPID = await dispatchMatch(
javaPath,
Expand All @@ -63,10 +68,9 @@ export function useScaffold(): Scaffold {
appContext.state.config.validateMaps,
shouldProfile
)
setConsoleLines([])
matchPID.current = newPID
} catch (e: any) {
setConsoleLines([{ content: e, type: 'error' }])
consoleLines.current.push({ content: e, type: 'error' })
}
forceUpdate()
}
Expand Down Expand Up @@ -193,7 +197,7 @@ export function useScaffold(): Scaffold {
loading,
runMatch,
matchPID.current ? killMatch : undefined,
consoleLines
consoleLines.current
]
}

Expand Down
23 changes: 21 additions & 2 deletions client/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { schema } from 'battlecode-schema'

export const GAME_VERSION = '2.0.2'
export const SPEC_VERSION = '2.0.2'
export const GAME_VERSION = '3.0.0'
export const SPEC_VERSION = '3.0.0'
export const BATTLECODE_YEAR: number = 2024
export const MAP_SIZE_RANGE = {
min: 30,
Expand All @@ -28,6 +28,24 @@ export const ENGINE_BUILTIN_MAP_NAMES: string[] = [
'DefaultMedium',
'DefaultLarge',
'DefaultHuge',
'BedWars',
'Bunkers',
'Checkered',
'Diagonal',
'Divergent',
'EndAround',
'FloodGates',
'Foxes',
'Fusbol',
'GaltonBoard',
'HeMustBeFreed',
'Intercontinental',
'Klein',
'QueenOfHearts',
'QuestionableChess',
'Racetrack',
'Rainbow',
'TreeSearch',
'AceOfSpades',
'Alien',
'Ambush',
Expand All @@ -38,6 +56,7 @@ export const ENGINE_BUILTIN_MAP_NAMES: string[] = [
'Duck',
'Fountain',
'Hockey',
'HungerGames',
'MazeRunner',
'Rivers',
'Snake',
Expand Down
2 changes: 1 addition & 1 deletion client/src/playback/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export const ACTION_DEFINITIONS: Record<schema.Action, typeof Action> = {
[schema.Action.GLOBAL_UPGRADE]: class GlobalUpgrade extends Action {
apply(turn: Turn): void {
const team = turn.bodies.getById(this.robotID).team
turn.stat.getTeamStat(team).globalUpgrades.add(this.target)
turn.stat.getTeamStat(team).globalUpgrades.push(this.target)
}
}
}
6 changes: 3 additions & 3 deletions client/src/playback/TurnStat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ export class TeamTurnStat {
specializationTotalLevels: [number, number, number, number, number] = [0, 0, 0, 0, 0]
resourceAmount: number = 0
resourceAmountAverageDatapoint: number | undefined = undefined
globalUpgrades: Set<schema.GlobalUpgradeType> = new Set()
globalUpgrades: schema.GlobalUpgradeType[] = []

copy(): TeamTurnStat {
const newStat = Object.assign(Object.create(Object.getPrototypeOf(this)), this)
const newStat: TeamTurnStat = Object.assign(Object.create(Object.getPrototypeOf(this)), this)

// Copy any internal objects here
newStat.robots = [...this.robots]
newStat.specializationTotalLevels = [...this.specializationTotalLevels]
newStat.globalUpgrades = new Set(this.globalUpgrades)
newStat.globalUpgrades = [...this.globalUpgrades]

return newStat
}
Expand Down
53 changes: 53 additions & 0 deletions client/src/util/ring-buffer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
export class RingBuffer<T> {
private _array: T[]
private _effectiveLength: number

constructor(n: number) {
this._array = new Array(n)
this._effectiveLength = 0
}

public toString() {
return '[object RingBuffer(' + this._array.length + ') effectiveLength ' + this._effectiveLength + ']'
}

public length() {
return Math.min(this._array.length, this._effectiveLength)
}

public effectiveLength() {
return this._effectiveLength
}

public get(i: number) {
if (i < 0 || i >= this.length()) return undefined
const index = this.computeActualIndex(i)
return this._array[index]
}

public set(i: number, v: T) {
if (i < 0 || i >= this.length()) throw new Error('set() Index out of range')
const index = this.computeActualIndex(i)
this._array[index] = v
}

public push(v: T) {
const index = this.computeActualIndex(this._effectiveLength)
this._array[index] = v
this._effectiveLength++
}

public clear() {
this._effectiveLength = 0
}

public *[Symbol.iterator]() {
for (let i = 0; i < this.length(); i++) {
yield this.get(i)
}
}

private computeActualIndex(offset: number) {
return Math.max((this._effectiveLength - this._array.length, 0) + offset) % this._array.length
}
}
4 changes: 2 additions & 2 deletions engine/src/main/battlecode/common/GameConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class GameConstants {
/**
* The current spec version the server compiles with.
*/
public static final String SPEC_VERSION = "2.0.2";
public static final String SPEC_VERSION = "3.0.0";

// *********************************
// ****** MAP CONSTANTS ************
Expand Down Expand Up @@ -90,7 +90,7 @@ public class GameConstants {
public static final int PASSIVE_CRUMBS_INCREASE = 10;

/** The amount of crumbs you gain if your bot kills an enemy while in enemy territory */
public static final int KILL_CRUMB_REWARD = 50;
public static final int KILL_CRUMB_REWARD = 30;

/** The end of the setup rounds in the game */
public static final int SETUP_ROUNDS = 200;
Expand Down
Loading

0 comments on commit 2472926

Please sign in to comment.