diff --git a/sprites/nodes/ocelot-block/Default.png b/sprites/nodes/ocelot-block/Default.png new file mode 100644 index 0000000..3b5247c Binary files /dev/null and b/sprites/nodes/ocelot-block/Default.png differ diff --git a/sprites/nodes/ocelot-block/Rx.png b/sprites/nodes/ocelot-block/Rx.png new file mode 100644 index 0000000..dcb823c Binary files /dev/null and b/sprites/nodes/ocelot-block/Rx.png differ diff --git a/sprites/nodes/ocelot-block/Tx.png b/sprites/nodes/ocelot-block/Tx.png new file mode 100644 index 0000000..770d4b0 Binary files /dev/null and b/sprites/nodes/ocelot-block/Tx.png differ diff --git a/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.png b/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.png index c0f79d0..bf5252f 100644 Binary files a/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.png and b/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.png differ diff --git a/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.txt b/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.txt index 25a33fd..213b10d 100644 --- a/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.txt +++ b/src/main/resources/ocelot/desktop/images/spritesheet/spritesheet.txt @@ -1,324 +1,327 @@ BackgroundPattern 0 0 304 304 BarSegment 385 434 16 4 -Empty 249 655 16 16 -EmptySlot 220 707 18 18 +Empty 134 618 16 16 +EmptySlot 237 567 18 18 Knob 203 434 50 50 KnobCenter 254 434 50 50 KnobLimits 305 434 50 50 Loading 0 305 48 448 Logo 305 0 168 200 -ShadowBorder 279 305 1 24 -ShadowCorner 216 674 24 24 -TabArrow 134 634 8 14 -blocks/Generic 266 655 16 16 -blocks/HologramEffect 287 314 4 4 -blocks/HologramProjector1Top 283 655 16 16 -blocks/HologramProjector2Top 300 655 16 16 -blocks/HologramProjectorSide 317 655 16 16 -buttons/BottomDrawerClose 239 707 18 18 -buttons/BottomDrawerOpen 258 707 18 18 +ShadowBorder 201 540 1 24 +ShadowCorner 233 674 24 24 +TabArrow 225 600 8 14 +blocks/Generic 151 618 16 16 +blocks/HologramEffect 209 549 4 4 +blocks/HologramProjector1Top 168 618 16 16 +blocks/HologramProjector2Top 185 618 16 16 +blocks/HologramProjectorSide 202 618 16 16 +buttons/BottomDrawerClose 256 567 18 18 +buttons/BottomDrawerOpen 275 567 18 18 buttons/OpenFMRadioCloseOff 404 445 7 8 buttons/OpenFMRadioCloseOn 412 445 7 8 buttons/OpenFMRadioRedstoneOff 359 445 8 8 buttons/OpenFMRadioRedstoneOn 368 445 8 8 -buttons/OpenFMRadioStartOff 241 674 24 24 -buttons/OpenFMRadioStartOn 266 674 24 24 -buttons/OpenFMRadioStopOff 291 674 24 24 -buttons/OpenFMRadioStopOn 316 674 24 24 -buttons/OpenFMRadioVolumeDownOff 143 634 10 10 -buttons/OpenFMRadioVolumeDownOn 154 634 10 10 -buttons/OpenFMRadioVolumeUpOff 165 634 10 10 -buttons/OpenFMRadioVolumeUpOn 176 634 10 10 -buttons/PowerOff 277 707 18 18 -buttons/PowerOn 296 707 18 18 -buttons/RackRelayOff 117 655 65 18 -buttons/RackRelayOn 183 655 65 18 -icons/Antenna 334 655 16 16 -icons/ArrowRight 351 655 16 16 -icons/AspectRatio 368 655 16 16 -icons/Book 385 655 16 16 -icons/ButtonCheck 341 674 17 17 -icons/ButtonClipboard 359 674 17 17 -icons/ButtonRandomize 377 674 17 17 -icons/CPU 402 655 16 16 -icons/Card 419 655 16 16 -icons/Close 134 601 15 14 -icons/Code 436 655 16 16 -icons/ComponentBus 453 655 16 16 -icons/Copy 470 655 16 16 -icons/Cross 487 655 16 16 -icons/Delete 504 655 16 16 -icons/DragLMB 483 707 21 14 -icons/DragRMB 505 707 21 14 -icons/EEPROM 521 655 16 16 -icons/Edit 538 655 16 16 -icons/Eject 555 655 16 16 -icons/File 572 655 16 16 -icons/Floppy 589 655 16 16 -icons/Folder 606 655 16 16 -icons/FolderSlash 623 655 16 16 -icons/Grid 151 707 22 22 -icons/GridOff 174 707 22 22 -icons/Guitar 640 655 16 16 -icons/HDD 657 655 16 16 -icons/Help 674 655 16 16 -icons/Home 197 707 22 22 -icons/Keyboard 691 655 16 16 -icons/KeyboardOff 708 655 16 16 -icons/LMB 218 616 11 14 -icons/Label 725 655 16 16 -icons/LinesHorizontal 742 655 16 16 -icons/Link 759 655 16 16 -icons/LinkSlash 776 655 16 16 -icons/Memory 793 655 16 16 -icons/Microchip 810 655 16 16 -icons/NA 827 655 16 16 -icons/NotificationError 242 616 11 11 -icons/NotificationInfo 254 616 11 11 -icons/NotificationWarning 266 616 11 11 -icons/Ocelot 844 655 16 16 -icons/Pin 173 616 14 14 -icons/Plus 861 655 16 16 -icons/Power 878 655 16 16 -icons/RMB 230 616 11 14 -icons/Restart 895 655 16 16 -icons/Save 912 655 16 16 -icons/SaveAs 929 655 16 16 -icons/Server 946 655 16 16 -icons/SettingsSound 134 616 12 17 -icons/SettingsSystem 147 616 12 17 -icons/SettingsUI 160 616 12 17 -icons/Tier0 963 655 16 16 -icons/Tier1 980 655 16 16 -icons/Tier2 997 655 16 16 -icons/Tiers 201 540 16 16 -icons/Unpin 188 616 14 14 -icons/WaveLFSR 833 584 24 10 -icons/WaveNoise 858 584 24 10 -icons/WaveSawtooth 883 584 24 10 -icons/WaveSine 908 584 24 10 -icons/WaveSquare 933 584 24 10 -icons/WaveTriangle 958 584 24 10 -icons/Window 218 540 16 16 -icons/WireArrowLeft 281 305 4 8 -icons/WireArrowRight 286 305 4 8 +buttons/OpenFMRadioStartOff 258 674 24 24 +buttons/OpenFMRadioStartOn 283 674 24 24 +buttons/OpenFMRadioStopOff 308 674 24 24 +buttons/OpenFMRadioStopOn 333 674 24 24 +buttons/OpenFMRadioVolumeDownOff 234 600 10 10 +buttons/OpenFMRadioVolumeDownOn 245 600 10 10 +buttons/OpenFMRadioVolumeUpOff 256 600 10 10 +buttons/OpenFMRadioVolumeUpOn 267 600 10 10 +buttons/PowerOff 294 567 18 18 +buttons/PowerOn 313 567 18 18 +buttons/RackRelayOff 134 655 65 18 +buttons/RackRelayOn 200 655 65 18 +icons/Antenna 219 618 16 16 +icons/ArrowRight 236 618 16 16 +icons/AspectRatio 253 618 16 16 +icons/Book 270 618 16 16 +icons/ButtonCheck 134 600 17 17 +icons/ButtonClipboard 152 600 17 17 +icons/ButtonRandomize 170 600 17 17 +icons/CPU 287 618 16 16 +icons/Card 304 618 16 16 +icons/Close 209 600 15 14 +icons/Code 321 618 16 16 +icons/ComponentBus 338 618 16 16 +icons/Copy 355 618 16 16 +icons/Cross 372 618 16 16 +icons/Delete 389 618 16 16 +icons/DragLMB 500 567 21 14 +icons/DragRMB 522 567 21 14 +icons/EEPROM 406 618 16 16 +icons/Edit 423 618 16 16 +icons/Eject 440 618 16 16 +icons/File 457 618 16 16 +icons/Floppy 474 618 16 16 +icons/Folder 491 618 16 16 +icons/FolderSlash 508 618 16 16 +icons/Grid 168 567 22 22 +icons/GridOff 191 567 22 22 +icons/Guitar 525 618 16 16 +icons/HDD 542 618 16 16 +icons/Help 559 618 16 16 +icons/Home 214 567 22 22 +icons/Keyboard 576 618 16 16 +icons/KeyboardOff 593 618 16 16 +icons/LMB 350 655 11 14 +icons/Label 610 618 16 16 +icons/LinesHorizontal 627 618 16 16 +icons/Link 644 618 16 16 +icons/LinkSlash 661 618 16 16 +icons/Memory 678 618 16 16 +icons/Microchip 695 618 16 16 +icons/NA 712 618 16 16 +icons/NotificationError 374 655 11 11 +icons/NotificationInfo 386 655 11 11 +icons/NotificationWarning 398 655 11 11 +icons/Ocelot 729 618 16 16 +icons/Pin 305 655 14 14 +icons/Plus 746 618 16 16 +icons/Power 763 618 16 16 +icons/RMB 362 655 11 14 +icons/Restart 780 618 16 16 +icons/Save 797 618 16 16 +icons/SaveAs 814 618 16 16 +icons/Server 831 618 16 16 +icons/SettingsSound 266 655 12 17 +icons/SettingsSystem 279 655 12 17 +icons/SettingsUI 292 655 12 17 +icons/Tier0 848 618 16 16 +icons/Tier1 865 618 16 16 +icons/Tier2 882 618 16 16 +icons/Tiers 899 618 16 16 +icons/Unpin 320 655 14 14 +icons/WaveLFSR 901 707 24 10 +icons/WaveNoise 926 707 24 10 +icons/WaveSawtooth 951 707 24 10 +icons/WaveSine 976 707 24 10 +icons/WaveSquare 134 724 24 10 +icons/WaveTriangle 159 724 24 10 +icons/Window 916 618 16 16 +icons/WireArrowLeft 203 540 4 8 +icons/WireArrowRight 208 540 4 8 items/APU0 49 655 16 96 items/APU1 66 655 16 96 items/APU2 83 655 16 96 -items/CPU0 235 540 16 16 -items/CPU1 252 540 16 16 -items/CPU2 269 540 16 16 -items/CardBase 286 540 16 16 -items/CircuitBoard 303 540 16 16 -items/ComponentBus0 320 540 16 16 -items/ComponentBus1 337 540 16 16 -items/ComponentBus2 354 540 16 16 -items/ComponentBus3 371 540 16 16 +items/CPU0 933 618 16 16 +items/CPU1 950 618 16 16 +items/CPU2 967 618 16 16 +items/CardBase 984 618 16 16 +items/CircuitBoard 1001 618 16 16 +items/ComponentBus0 134 635 16 16 +items/ComponentBus1 151 635 16 16 +items/ComponentBus2 168 635 16 16 +items/ComponentBus3 185 635 16 16 items/DataCard0 49 526 16 128 items/DataCard1 66 526 16 128 items/DataCard2 83 526 16 128 -items/DebugCard 388 540 16 16 -items/DiskDriveMountable 405 540 16 16 -items/EEPROM 422 540 16 16 -items/FloppyDisk_dyeBlack 439 540 16 16 -items/FloppyDisk_dyeBlue 456 540 16 16 -items/FloppyDisk_dyeBrown 473 540 16 16 -items/FloppyDisk_dyeCyan 490 540 16 16 -items/FloppyDisk_dyeGray 507 540 16 16 -items/FloppyDisk_dyeGreen 524 540 16 16 -items/FloppyDisk_dyeLightBlue 541 540 16 16 -items/FloppyDisk_dyeLightGray 558 540 16 16 -items/FloppyDisk_dyeLime 575 540 16 16 -items/FloppyDisk_dyeMagenta 592 540 16 16 -items/FloppyDisk_dyeOrange 609 540 16 16 -items/FloppyDisk_dyePink 626 540 16 16 -items/FloppyDisk_dyePurple 643 540 16 16 -items/FloppyDisk_dyeRed 660 540 16 16 -items/FloppyDisk_dyeWhite 677 540 16 16 -items/FloppyDisk_dyeYellow 694 540 16 16 -items/GraphicsCard0 711 540 16 16 -items/GraphicsCard1 728 540 16 16 -items/GraphicsCard2 745 540 16 16 -items/HardDiskDrive0 762 540 16 16 -items/HardDiskDrive1 779 540 16 16 -items/HardDiskDrive2 796 540 16 16 -items/InternetCard 117 707 16 32 +items/DebugCard 202 635 16 16 +items/DiskDriveMountable 219 635 16 16 +items/EEPROM 236 635 16 16 +items/FloppyDisk_dyeBlack 253 635 16 16 +items/FloppyDisk_dyeBlue 270 635 16 16 +items/FloppyDisk_dyeBrown 287 635 16 16 +items/FloppyDisk_dyeCyan 304 635 16 16 +items/FloppyDisk_dyeGray 321 635 16 16 +items/FloppyDisk_dyeGreen 338 635 16 16 +items/FloppyDisk_dyeLightBlue 355 635 16 16 +items/FloppyDisk_dyeLightGray 372 635 16 16 +items/FloppyDisk_dyeLime 389 635 16 16 +items/FloppyDisk_dyeMagenta 406 635 16 16 +items/FloppyDisk_dyeOrange 423 635 16 16 +items/FloppyDisk_dyePink 440 635 16 16 +items/FloppyDisk_dyePurple 457 635 16 16 +items/FloppyDisk_dyeRed 474 635 16 16 +items/FloppyDisk_dyeWhite 491 635 16 16 +items/FloppyDisk_dyeYellow 508 635 16 16 +items/GraphicsCard0 525 635 16 16 +items/GraphicsCard1 542 635 16 16 +items/GraphicsCard2 559 635 16 16 +items/HardDiskDrive0 576 635 16 16 +items/HardDiskDrive1 593 635 16 16 +items/HardDiskDrive2 610 635 16 16 +items/InternetCard 134 567 16 32 items/LinkedCard 100 655 16 96 -items/Memory0 813 540 16 16 -items/Memory1 830 540 16 16 -items/Memory2 847 540 16 16 -items/Memory3 864 540 16 16 -items/Memory4 881 540 16 16 -items/Memory5 898 540 16 16 -items/Memory6 915 540 16 16 -items/NetworkCard 932 540 16 16 +items/Memory0 627 635 16 16 +items/Memory1 644 635 16 16 +items/Memory2 661 635 16 16 +items/Memory3 678 635 16 16 +items/Memory4 695 635 16 16 +items/Memory5 712 635 16 16 +items/Memory6 729 635 16 16 +items/NetworkCard 746 635 16 16 items/OcelotCard 100 526 16 128 -items/RedstoneCard0 949 540 16 16 -items/RedstoneCard1 966 540 16 16 -items/SelfDestructingCard 134 707 16 32 -items/Server0 983 540 16 16 -items/Server1 1000 540 16 16 -items/Server2 134 567 16 16 -items/Server3 151 567 16 16 +items/RedstoneCard0 763 635 16 16 +items/RedstoneCard1 780 635 16 16 +items/SelfDestructingCard 151 567 16 32 +items/Server0 797 635 16 16 +items/Server1 814 635 16 16 +items/Server2 831 635 16 16 +items/Server3 848 635 16 16 items/SoundCard 117 526 16 128 -items/TapeCopper 168 567 16 16 -items/TapeDiamond 185 567 16 16 -items/TapeGold 202 567 16 16 -items/TapeGreg 219 567 16 16 -items/TapeIg 236 567 16 16 -items/TapeIron 253 567 16 16 -items/TapeNetherStar 270 567 16 16 -items/TapeSteel 287 567 16 16 -items/WirelessNetworkCard0 304 567 16 16 -items/WirelessNetworkCard1 321 567 16 16 -light-panel/BookmarkLeft 814 584 18 14 -light-panel/BookmarkRight 395 674 20 14 -light-panel/BorderB 292 314 4 4 -light-panel/BorderL 382 314 4 2 -light-panel/BorderR 297 314 4 4 -light-panel/BorderT 302 314 4 4 -light-panel/CornerBL 307 314 4 4 -light-panel/CornerBR 312 314 4 4 -light-panel/CornerTL 317 314 4 4 -light-panel/CornerTR 322 314 4 4 -light-panel/Fill 285 325 2 2 +items/TapeCopper 865 635 16 16 +items/TapeDiamond 882 635 16 16 +items/TapeGold 899 635 16 16 +items/TapeGreg 916 635 16 16 +items/TapeIg 933 635 16 16 +items/TapeIron 950 635 16 16 +items/TapeNetherStar 967 635 16 16 +items/TapeSteel 984 635 16 16 +items/WirelessNetworkCard0 1001 635 16 16 +items/WirelessNetworkCard1 358 674 16 16 +light-panel/BookmarkLeft 882 707 18 14 +light-panel/BookmarkRight 188 600 20 14 +light-panel/BorderB 214 549 4 4 +light-panel/BorderL 304 549 4 2 +light-panel/BorderR 219 549 4 4 +light-panel/BorderT 224 549 4 4 +light-panel/CornerBL 229 549 4 4 +light-panel/CornerBR 234 549 4 4 +light-panel/CornerTL 239 549 4 4 +light-panel/CornerTR 244 549 4 4 +light-panel/Fill 207 560 2 2 light-panel/Vent 356 434 2 38 nodes/Cable 377 445 8 8 -nodes/Camera 338 567 16 16 -nodes/Chest 203 616 14 14 -nodes/HologramProjector0 355 567 16 16 -nodes/HologramProjector1 372 567 16 16 -nodes/IronNoteBlock 389 567 16 16 -nodes/Lamp 406 567 16 16 -nodes/LampFrame 423 567 16 16 +nodes/Camera 375 674 16 16 +nodes/Chest 335 655 14 14 +nodes/HologramProjector0 392 674 16 16 +nodes/HologramProjector1 409 674 16 16 +nodes/IronNoteBlock 426 674 16 16 +nodes/Lamp 443 674 16 16 +nodes/LampFrame 460 674 16 16 nodes/LampGlow 49 305 128 128 -nodes/NewNode 440 567 16 16 -nodes/NoteBlock 457 567 16 16 -nodes/OpenFMRadio 474 567 16 16 -nodes/Relay 491 567 16 16 -nodes/TapeDrive 508 567 16 16 -nodes/computer/Default 525 567 16 16 -nodes/computer/DiskActivity 542 567 16 16 -nodes/computer/Error 559 567 16 16 -nodes/computer/On 576 567 16 16 -nodes/disk-drive/Default 593 567 16 16 -nodes/disk-drive/DiskActivity 610 567 16 16 -nodes/disk-drive/Floppy 627 567 16 16 -nodes/holidays/Christmas 117 674 32 32 -nodes/holidays/Halloween 150 674 32 32 -nodes/holidays/Valentines 183 674 32 32 -nodes/microcontroller/Default 644 567 16 16 -nodes/microcontroller/Error 661 567 16 16 -nodes/microcontroller/On 678 567 16 16 -nodes/rack/Default 695 567 16 16 -nodes/rack/Empty 712 567 16 16 -nodes/rack/drive/0/Default 729 567 16 16 -nodes/rack/drive/0/DiskActivity 746 567 16 16 -nodes/rack/drive/0/Floppy 763 567 16 16 -nodes/rack/drive/1/Default 780 567 16 16 -nodes/rack/drive/1/DiskActivity 797 567 16 16 -nodes/rack/drive/1/Floppy 814 567 16 16 -nodes/rack/drive/2/Default 831 567 16 16 -nodes/rack/drive/2/DiskActivity 848 567 16 16 -nodes/rack/drive/2/Floppy 865 567 16 16 -nodes/rack/drive/3/Default 882 567 16 16 -nodes/rack/drive/3/DiskActivity 899 567 16 16 -nodes/rack/drive/3/Floppy 916 567 16 16 -nodes/rack/drive/Floppy 933 567 16 16 -nodes/rack/server/0/Default 950 567 16 16 -nodes/rack/server/0/DiskActivity 967 567 16 16 -nodes/rack/server/0/Error 984 567 16 16 -nodes/rack/server/0/NetworkActivity 1001 567 16 16 -nodes/rack/server/0/On 134 584 16 16 -nodes/rack/server/1/Default 151 584 16 16 -nodes/rack/server/1/DiskActivity 168 584 16 16 -nodes/rack/server/1/Error 185 584 16 16 -nodes/rack/server/1/NetworkActivity 202 584 16 16 -nodes/rack/server/1/On 219 584 16 16 -nodes/rack/server/2/Default 236 584 16 16 -nodes/rack/server/2/DiskActivity 253 584 16 16 -nodes/rack/server/2/Error 270 584 16 16 -nodes/rack/server/2/NetworkActivity 287 584 16 16 -nodes/rack/server/2/On 304 584 16 16 -nodes/rack/server/3/Default 321 584 16 16 -nodes/rack/server/3/DiskActivity 338 584 16 16 -nodes/rack/server/3/Error 355 584 16 16 -nodes/rack/server/3/NetworkActivity 372 584 16 16 -nodes/rack/server/3/On 389 584 16 16 -nodes/raid/0/DiskActivity 406 584 16 16 -nodes/raid/0/Error 423 584 16 16 -nodes/raid/1/DiskActivity 440 584 16 16 -nodes/raid/1/Error 457 584 16 16 -nodes/raid/2/DiskActivity 474 584 16 16 -nodes/raid/2/Error 491 584 16 16 -nodes/raid/Default 508 584 16 16 -nodes/screen/BottomLeft 525 584 16 16 -nodes/screen/BottomMiddle 542 584 16 16 -nodes/screen/BottomRight 559 584 16 16 -nodes/screen/ColumnBottom 576 584 16 16 -nodes/screen/ColumnMiddle 593 584 16 16 -nodes/screen/ColumnTop 610 584 16 16 -nodes/screen/Middle 627 584 16 16 -nodes/screen/MiddleLeft 644 584 16 16 -nodes/screen/MiddleRight 661 584 16 16 -nodes/screen/PowerOnOverlay 678 584 16 16 -nodes/screen/RowLeft 695 584 16 16 -nodes/screen/RowMiddle 712 584 16 16 -nodes/screen/RowRight 729 584 16 16 -nodes/screen/Standalone 746 584 16 16 -nodes/screen/TopLeft 763 584 16 16 -nodes/screen/TopMiddle 780 584 16 16 -nodes/screen/TopRight 797 584 16 16 -panel/BorderB 327 314 4 4 -panel/BorderL 387 314 4 2 -panel/BorderR 332 314 4 4 -panel/BorderT 337 314 4 4 -panel/CornerBL 342 314 4 4 -panel/CornerBR 347 314 4 4 -panel/CornerTL 352 314 4 4 -panel/CornerTR 357 314 4 4 -panel/Fill 288 325 2 2 +nodes/NewNode 477 674 16 16 +nodes/NoteBlock 494 674 16 16 +nodes/OpenFMRadio 511 674 16 16 +nodes/Relay 528 674 16 16 +nodes/TapeDrive 545 674 16 16 +nodes/computer/Default 562 674 16 16 +nodes/computer/DiskActivity 579 674 16 16 +nodes/computer/Error 596 674 16 16 +nodes/computer/On 613 674 16 16 +nodes/disk-drive/Default 630 674 16 16 +nodes/disk-drive/DiskActivity 647 674 16 16 +nodes/disk-drive/Floppy 664 674 16 16 +nodes/holidays/Christmas 134 674 32 32 +nodes/holidays/Halloween 167 674 32 32 +nodes/holidays/Valentines 200 674 32 32 +nodes/microcontroller/Default 681 674 16 16 +nodes/microcontroller/Error 698 674 16 16 +nodes/microcontroller/On 715 674 16 16 +nodes/ocelot-block/Default 117 655 16 80 +nodes/ocelot-block/Rx 732 674 16 16 +nodes/ocelot-block/Tx 749 674 16 16 +nodes/rack/Default 766 674 16 16 +nodes/rack/Empty 783 674 16 16 +nodes/rack/drive/0/Default 800 674 16 16 +nodes/rack/drive/0/DiskActivity 817 674 16 16 +nodes/rack/drive/0/Floppy 834 674 16 16 +nodes/rack/drive/1/Default 851 674 16 16 +nodes/rack/drive/1/DiskActivity 868 674 16 16 +nodes/rack/drive/1/Floppy 885 674 16 16 +nodes/rack/drive/2/Default 902 674 16 16 +nodes/rack/drive/2/DiskActivity 919 674 16 16 +nodes/rack/drive/2/Floppy 936 674 16 16 +nodes/rack/drive/3/Default 953 674 16 16 +nodes/rack/drive/3/DiskActivity 970 674 16 16 +nodes/rack/drive/3/Floppy 987 674 16 16 +nodes/rack/drive/Floppy 1004 674 16 16 +nodes/rack/server/0/Default 134 707 16 16 +nodes/rack/server/0/DiskActivity 151 707 16 16 +nodes/rack/server/0/Error 168 707 16 16 +nodes/rack/server/0/NetworkActivity 185 707 16 16 +nodes/rack/server/0/On 202 707 16 16 +nodes/rack/server/1/Default 219 707 16 16 +nodes/rack/server/1/DiskActivity 236 707 16 16 +nodes/rack/server/1/Error 253 707 16 16 +nodes/rack/server/1/NetworkActivity 270 707 16 16 +nodes/rack/server/1/On 287 707 16 16 +nodes/rack/server/2/Default 304 707 16 16 +nodes/rack/server/2/DiskActivity 321 707 16 16 +nodes/rack/server/2/Error 338 707 16 16 +nodes/rack/server/2/NetworkActivity 355 707 16 16 +nodes/rack/server/2/On 372 707 16 16 +nodes/rack/server/3/Default 389 707 16 16 +nodes/rack/server/3/DiskActivity 406 707 16 16 +nodes/rack/server/3/Error 423 707 16 16 +nodes/rack/server/3/NetworkActivity 440 707 16 16 +nodes/rack/server/3/On 457 707 16 16 +nodes/raid/0/DiskActivity 474 707 16 16 +nodes/raid/0/Error 491 707 16 16 +nodes/raid/1/DiskActivity 508 707 16 16 +nodes/raid/1/Error 525 707 16 16 +nodes/raid/2/DiskActivity 542 707 16 16 +nodes/raid/2/Error 559 707 16 16 +nodes/raid/Default 576 707 16 16 +nodes/screen/BottomLeft 593 707 16 16 +nodes/screen/BottomMiddle 610 707 16 16 +nodes/screen/BottomRight 627 707 16 16 +nodes/screen/ColumnBottom 644 707 16 16 +nodes/screen/ColumnMiddle 661 707 16 16 +nodes/screen/ColumnTop 678 707 16 16 +nodes/screen/Middle 695 707 16 16 +nodes/screen/MiddleLeft 712 707 16 16 +nodes/screen/MiddleRight 729 707 16 16 +nodes/screen/PowerOnOverlay 746 707 16 16 +nodes/screen/RowLeft 763 707 16 16 +nodes/screen/RowMiddle 780 707 16 16 +nodes/screen/RowRight 797 707 16 16 +nodes/screen/Standalone 814 707 16 16 +nodes/screen/TopLeft 831 707 16 16 +nodes/screen/TopMiddle 848 707 16 16 +nodes/screen/TopRight 865 707 16 16 +panel/BorderB 249 549 4 4 +panel/BorderL 309 549 4 2 +panel/BorderR 254 549 4 4 +panel/BorderT 259 549 4 4 +panel/CornerBL 264 549 4 4 +panel/CornerBR 269 549 4 4 +panel/CornerTL 274 549 4 4 +panel/CornerTR 279 549 4 4 +panel/Fill 210 560 2 2 particles/Note 377 434 7 10 -screen/BorderB 284 314 2 8 -screen/BorderT 281 314 2 10 +screen/BorderB 206 549 2 8 +screen/BorderT 203 549 2 10 screen/CornerBL 386 445 8 8 screen/CornerBR 395 445 8 8 screen/CornerTL 359 434 8 10 screen/CornerTR 368 434 8 10 -window/BorderDark 281 325 1 4 -window/BorderLight 283 325 1 4 -window/CornerBL 362 314 4 4 -window/CornerBR 367 314 4 4 -window/CornerTL 372 314 4 4 -window/CornerTR 377 314 4 4 +window/BorderDark 203 560 1 4 +window/BorderLight 205 560 1 4 +window/CornerBL 284 549 4 4 +window/CornerBR 289 549 4 4 +window/CornerTL 294 549 4 4 +window/CornerTR 299 549 4 4 window/OpenFMRadio 474 0 232 105 window/case/Motherboard 123 434 79 70 window/rack/Lines 49 434 73 91 window/rack/Motherboard 178 305 100 78 -window/rack/NetworkBack 299 319 1 2 -window/rack/NetworkBottom 301 319 1 2 -window/rack/NetworkConnector 303 319 1 2 -window/rack/NetworkLeft 305 319 1 2 -window/rack/NetworkRight 307 319 1 2 -window/rack/NetworkTop 309 319 1 2 -window/rack/NodeBack 392 314 5 1 -window/rack/NodeBottom 398 314 5 1 -window/rack/NodeLeft 404 314 5 1 -window/rack/NodeRight 410 314 5 1 -window/rack/NodeTop 416 314 5 1 -window/rack/SideBack 287 319 1 3 -window/rack/SideBottom 289 319 1 3 -window/rack/SideConnector 291 319 1 3 -window/rack/SideLeft 293 319 1 3 -window/rack/SideRight 295 319 1 3 -window/rack/SideTop 297 319 1 3 +window/rack/NetworkBack 221 554 1 2 +window/rack/NetworkBottom 223 554 1 2 +window/rack/NetworkConnector 225 554 1 2 +window/rack/NetworkLeft 227 554 1 2 +window/rack/NetworkRight 229 554 1 2 +window/rack/NetworkTop 231 554 1 2 +window/rack/NodeBack 314 549 5 1 +window/rack/NodeBottom 320 549 5 1 +window/rack/NodeLeft 326 549 5 1 +window/rack/NodeRight 332 549 5 1 +window/rack/NodeTop 338 549 5 1 +window/rack/SideBack 209 554 1 3 +window/rack/SideBottom 211 554 1 3 +window/rack/SideConnector 213 554 1 3 +window/rack/SideLeft 215 554 1 3 +window/rack/SideRight 217 554 1 3 +window/rack/SideTop 219 554 1 3 window/raid/Slots 134 540 66 26 -window/tape/Back 315 707 20 15 -window/tape/BackPressed 336 707 20 15 -window/tape/Forward 357 707 20 15 -window/tape/ForwardPressed 378 707 20 15 -window/tape/Play 399 707 20 15 -window/tape/PlayPressed 420 707 20 15 +window/tape/Back 332 567 20 15 +window/tape/BackPressed 353 567 20 15 +window/tape/Forward 374 567 20 15 +window/tape/ForwardPressed 395 567 20 15 +window/tape/Play 416 567 20 15 +window/tape/PlayPressed 437 567 20 15 window/tape/Screen 134 526 146 13 -window/tape/Stop 441 707 20 15 -window/tape/StopPressed 462 707 20 15 +window/tape/Stop 458 567 20 15 +window/tape/StopPressed 479 567 20 15 diff --git a/src/main/scala/ocelot/desktop/entity/OcelotBlock.scala b/src/main/scala/ocelot/desktop/entity/OcelotBlock.scala new file mode 100644 index 0000000..f71d2fd --- /dev/null +++ b/src/main/scala/ocelot/desktop/entity/OcelotBlock.scala @@ -0,0 +1,22 @@ +package ocelot.desktop.entity + +import ocelot.desktop.entity.traits.OcelotInterface +import totoro.ocelot.brain.Constants +import totoro.ocelot.brain.entity.traits.DeviceInfo +import totoro.ocelot.brain.entity.traits.DeviceInfo.{DeviceAttribute, DeviceClass} +import totoro.ocelot.brain.network.{Network, Node, Visibility} + +class OcelotBlock extends OcelotInterface with DeviceInfo { + override val node: Node = Network.newNode(this, Visibility.Network) + .withComponent("ocelot", Visibility.Network) + .create() + + private final lazy val deviceInfo = Map( + DeviceAttribute.Class -> DeviceClass.Generic, + DeviceAttribute.Description -> "Cardboard box simulator", + DeviceAttribute.Vendor -> Constants.DeviceInfo.DefaultVendor, + DeviceAttribute.Product -> "Catbus", + ) + + override def getDeviceInfo: Map[String, String] = deviceInfo +} diff --git a/src/main/scala/ocelot/desktop/entity/OcelotCard.scala b/src/main/scala/ocelot/desktop/entity/OcelotCard.scala index f103547..4b147e0 100644 --- a/src/main/scala/ocelot/desktop/entity/OcelotCard.scala +++ b/src/main/scala/ocelot/desktop/entity/OcelotCard.scala @@ -1,18 +1,14 @@ package ocelot.desktop.entity -import ocelot.desktop.entity.OcelotCard.LogEvent +import ocelot.desktop.entity.traits.OcelotInterface import totoro.ocelot.brain.Constants -import totoro.ocelot.brain.entity.machine.{Arguments, Callback, Context} import totoro.ocelot.brain.entity.traits.DeviceInfo.{DeviceAttribute, DeviceClass} -import totoro.ocelot.brain.entity.traits.{DeviceInfo, Entity, Environment, Tiered, result} -import totoro.ocelot.brain.event.{EventBus, NodeEvent} +import totoro.ocelot.brain.entity.traits.{DeviceInfo, Tiered} import totoro.ocelot.brain.network.{Network, Node, Visibility} import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier.Tier -import java.time.Instant - -class OcelotCard extends Entity with Environment with DeviceInfo with Tiered { +class OcelotCard extends OcelotInterface with DeviceInfo with Tiered { override val node: Node = Network.newNode(this, Visibility.Neighbors) .withComponent("ocelot", Visibility.Neighbors) .create() @@ -27,52 +23,4 @@ class OcelotCard extends Entity with Environment with DeviceInfo with Tiered { ) override def getDeviceInfo: Map[String, String] = deviceInfo - - @Callback(direct = true, doc = """function(message: string) -- Logs a message to the card's console.""") - def log(context: Context, args: Arguments): Array[AnyRef] = { - val message = args.checkString(0) - EventBus.send(LogEvent.CardToUser(node.address, message)) - result() - } - - @Callback(direct = true, doc = """function() -- Clears messages logged to the card's console.""") - def clearLog(context: Context, args: Arguments): Array[AnyRef] = { - EventBus.send(LogEvent.Clear(node.address)) - result() - } - - @Callback(direct = true, doc = """function(): integer -- Returns the current Unix timestamp (UTC, in milliseconds).""") - def getTimestamp(context: Context, args: Arguments): Array[AnyRef] = { - result(Instant.now().toEpochMilli) - } - - @Callback(direct = true, doc = """function(): integer -- Returns a high-resolution timer value (in nanoseconds).""") - def getInstant(context: Context, args: Arguments): Array[AnyRef] = { - result(System.nanoTime()) - } - - @Callback(direct = true, doc = """function(): number -- Returns the remaining call budget.""") - def getRemainingCallBudget(context: Context, args: Arguments): Array[AnyRef] = { - result(context.getRemainingCallBudget) - } - - @Callback(direct = true, doc = """function(): number -- Returns the maximum call budget.""") - def getMaxCallBudget(context: Context, args: Arguments): Array[AnyRef] = { - result(context.getMaxCallBudget) - } - - def pushMessage(message: String): Unit = { - node.sendToReachable("computer.signal", "ocelot_message", message) - EventBus.send(LogEvent.UserToCard(node.address, message)) - } -} - -object OcelotCard { - sealed trait LogEvent extends NodeEvent - - object LogEvent { - case class CardToUser(address: String, message: String) extends LogEvent - case class UserToCard(address: String, message: String) extends LogEvent - case class Clear(address: String) extends LogEvent - } } diff --git a/src/main/scala/ocelot/desktop/entity/traits/OcelotInterface.scala b/src/main/scala/ocelot/desktop/entity/traits/OcelotInterface.scala new file mode 100644 index 0000000..3aa4193 --- /dev/null +++ b/src/main/scala/ocelot/desktop/entity/traits/OcelotInterface.scala @@ -0,0 +1,58 @@ +package ocelot.desktop.entity.traits + +import ocelot.desktop.entity.traits.OcelotInterface.LogEvent +import totoro.ocelot.brain.entity.machine.{Arguments, Callback, Context} +import totoro.ocelot.brain.entity.traits.{Entity, Environment, result} +import totoro.ocelot.brain.event.{EventBus, NodeEvent} + +import java.time.Instant + +trait OcelotInterface extends Entity with Environment { + @Callback(direct = true, doc = """function(message: string) -- Logs a message to the card's console.""") + def log(context: Context, args: Arguments): Array[AnyRef] = { + val message = args.checkString(0) + EventBus.send(LogEvent.CardToUser(node.address, message)) + result() + } + + @Callback(direct = true, doc = """function() -- Clears messages logged to the card's console.""") + def clearLog(context: Context, args: Arguments): Array[AnyRef] = { + EventBus.send(LogEvent.Clear(node.address)) + result() + } + + @Callback(direct = true, doc = """function(): integer -- Returns the current Unix timestamp (UTC, in milliseconds).""") + def getTimestamp(context: Context, args: Arguments): Array[AnyRef] = { + result(Instant.now().toEpochMilli) + } + + @Callback(direct = true, doc = """function(): integer -- Returns a high-resolution timer value (in nanoseconds).""") + def getInstant(context: Context, args: Arguments): Array[AnyRef] = { + result(System.nanoTime()) + } + + @Callback(direct = true, doc = """function(): number -- Returns the remaining call budget.""") + def getRemainingCallBudget(context: Context, args: Arguments): Array[AnyRef] = { + result(context.getRemainingCallBudget) + } + + @Callback(direct = true, doc = """function(): number -- Returns the maximum call budget.""") + def getMaxCallBudget(context: Context, args: Arguments): Array[AnyRef] = { + result(context.getMaxCallBudget) + } + + def pushMessage(message: String): Unit = { + node.sendToReachable("computer.signal", "ocelot_message", message) + EventBus.send(LogEvent.UserToCard(node.address, message)) + } +} + +object OcelotInterface { + sealed trait LogEvent extends NodeEvent + + object LogEvent { + case class CardToUser(address: String, message: String) extends LogEvent + case class UserToCard(address: String, message: String) extends LogEvent + case class Clear(address: String) extends LogEvent + } +} diff --git a/src/main/scala/ocelot/desktop/graphics/IconSource.scala b/src/main/scala/ocelot/desktop/graphics/IconSource.scala index 7ec2403..3e57f2f 100644 --- a/src/main/scala/ocelot/desktop/graphics/IconSource.scala +++ b/src/main/scala/ocelot/desktop/graphics/IconSource.scala @@ -8,8 +8,8 @@ import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier import totoro.ocelot.brain.util.Tier.Tier case class IconSource( - path: String, - animation: Option[IconSource.Animation] = None + path: String, + animation: Option[IconSource.Animation] = None, ) object IconSource { @@ -26,97 +26,92 @@ object IconSource { IconSource(s"icons/Tier${tier.id}") } - val Cpu: Tier => IconSource = { tier => - IconSource(s"items/CPU${tier.id}") - } + object Items { + val Cpu: Tier => IconSource = { tier => + IconSource(s"items/CPU${tier.id}") + } - val Apu: Tier => IconSource = { tier => - IconSource(s"items/APU${tier.id}", animation = Some(Animations.Apu)) - } + val Apu: Tier => IconSource = { tier => + IconSource(s"items/APU${tier.id}", animation = Some(Animations.Apu)) + } - val GraphicsCard: Tier => IconSource = { tier => - IconSource(s"items/GraphicsCard${tier.id}") - } + val GraphicsCard: Tier => IconSource = { tier => + IconSource(s"items/GraphicsCard${tier.id}") + } - val NetworkCard: IconSource = IconSource("items/NetworkCard") + val NetworkCard: IconSource = IconSource("items/NetworkCard") - val WirelessNetworkCard: Tier => IconSource = { tier => - IconSource(s"items/WirelessNetworkCard${tier.id}") - } + val WirelessNetworkCard: Tier => IconSource = { tier => + IconSource(s"items/WirelessNetworkCard${tier.id}") + } - val LinkedCard: IconSource = IconSource("items/LinkedCard", animation = Some(Animations.LinkedCard)) + val LinkedCard: IconSource = IconSource("items/LinkedCard", animation = Some(Animations.LinkedCard)) - val InternetCard: IconSource = IconSource("items/InternetCard", animation = Some(Animations.InternetCard)) + val InternetCard: IconSource = IconSource("items/InternetCard", animation = Some(Animations.InternetCard)) - val RedstoneCard: Tier => IconSource = { tier => - IconSource(s"items/RedstoneCard${tier.id}") - } + val RedstoneCard: Tier => IconSource = { tier => + IconSource(s"items/RedstoneCard${tier.id}") + } - val DataCard: Tier => IconSource = { tier => - IconSource(s"items/DataCard${tier.id}", animation = Some(Animations.DataCard)) - } + val DataCard: Tier => IconSource = { tier => + IconSource(s"items/DataCard${tier.id}", animation = Some(Animations.DataCard)) + } - val SoundCard: IconSource = IconSource("items/SoundCard", animation = Some(Animations.DataCard)) + val SoundCard: IconSource = IconSource("items/SoundCard", animation = Some(Animations.DataCard)) - val SelfDestructingCard: IconSource = IconSource("items/SelfDestructingCard", animation = Some(Animations.SelfDestructingCard)) + val SelfDestructingCard: IconSource = + IconSource("items/SelfDestructingCard", animation = Some(Animations.SelfDestructingCard)) - val OcelotCard: IconSource = IconSource("items/OcelotCard", animation = Some(Animations.OcelotCard)) + val OcelotCard: IconSource = IconSource("items/OcelotCard", animation = Some(Animations.OcelotCard)) - val HardDiskDrive: Tier => IconSource = { tier => - IconSource(s"items/HardDiskDrive${tier.id}") - } + val HardDiskDrive: Tier => IconSource = { tier => + IconSource(s"items/HardDiskDrive${tier.id}") + } - val Eeprom: IconSource = IconSource("items/EEPROM") + val Eeprom: IconSource = IconSource("items/EEPROM") - val FloppyDisk: DyeColor => IconSource = { color => - IconSource(s"items/FloppyDisk_${color.name}") - } + val FloppyDisk: DyeColor => IconSource = { color => + IconSource(s"items/FloppyDisk_${color.name}") + } - val Memory: ExtendedTier => IconSource = { tier => - IconSource(s"items/Memory${tier.id}") - } + val Memory: ExtendedTier => IconSource = { tier => + IconSource(s"items/Memory${tier.id}") + } - val Server: Tier => IconSource = { tier => - IconSource(s"items/Server${tier.id}") - } + val Server: Tier => IconSource = { tier => + IconSource(s"items/Server${tier.id}") + } - val ComponentBus: Tier => IconSource = { tier => - IconSource(s"items/ComponentBus${tier.id}") - } + val ComponentBus: Tier => IconSource = { tier => + IconSource(s"items/ComponentBus${tier.id}") + } - val Tape: TapeKind => IconSource = { - case TapeKind.Golder => Tape(TapeKind.Gold) - case TapeKind.NetherStarrer => Tape(TapeKind.NetherStar) - case kind => IconSource(s"items/Tape$kind") - } + val Tape: TapeKind => IconSource = { + case TapeKind.Golder => Tape(TapeKind.Gold) + case TapeKind.NetherStarrer => Tape(TapeKind.NetherStar) + case kind => IconSource(s"items/Tape$kind") + } - val DiskDriveMountable: IconSource = IconSource("items/DiskDriveMountable") + val DiskDriveMountable: IconSource = IconSource("items/DiskDriveMountable") - //noinspection ScalaWeakerAccess - object Animations { - val Apu: Animation = Animation( - (0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f), - (4, 3f), (3, 3f), (2, 3f), (1, 3f), (0, 3f)) + //noinspection ScalaWeakerAccess + object Animations { + val Apu: Animation = + Animation((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f), (4, 3f), (3, 3f), (2, 3f), (1, 3f), (0, 3f)) - val LinkedCard: Animation = - Animation((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f)) + val LinkedCard: Animation = + Animation((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f)) - val InternetCard: Animation = Animation( - (0, 2f), (1, 7f), (0, 5f), (1, 4f), (0, 7f), (1, 2f), (0, 8f), - (1, 9f), (0, 6f), (1, 4f)) + val InternetCard: Animation = + Animation((0, 2f), (1, 7f), (0, 5f), (1, 4f), (0, 7f), (1, 2f), (0, 8f), (1, 9f), (0, 6f), (1, 4f)) - val DataCard: Animation = Animation( - (0, 4f), (1, 4f), (2, 4f), (3, 4f), (4, 4f), (5, 4f), (6, 4f), (7, 4f)) + val DataCard: Animation = Animation((0, 4f), (1, 4f), (2, 4f), (3, 4f), (4, 4f), (5, 4f), (6, 4f), (7, 4f)) - val SelfDestructingCard: Animation = Animation((0, 4f), (1, 4f)) + val SelfDestructingCard: Animation = Animation((0, 4f), (1, 4f)) - val OcelotCard: Animation = Animation( - (0, 12f), (1, 4f), (2, 4f), (3, 4f), (4, 5f), (5, 6f), (0, 9f), (6, 4f), (7, 3f)) - - val Loading: Animation = Animation(Size2D(48, 32), - (0, 0.7f), (1, 0.7f), (2, 0.7f), (3, 0.7f), (4, 0.7f), (5, 0.7f), (6, 0.7f), - (7, 0.7f), (8, 0.7f), (9, 0.7f), (10, 0.7f), (11, 0.7f), (12, 0.7f), (13, 0.7f) - ) + val OcelotCard: Animation = + Animation((0, 12f), (1, 4f), (2, 4f), (3, 4f), (4, 5f), (5, 6f), (0, 9f), (6, 4f), (7, 3f)) + } } case class Animation(frames: Array[(Int, Float)], frameSize: Option[Size2D]) @@ -128,12 +123,27 @@ object IconSource { // ----------------------- Ocelot interface icons ----------------------- - val Notification: NotificationType => IconSource = { notificationType => IconSource(s"icons/Notification$notificationType") } - val Loading: IconSource = IconSource("Loading", animation = Some(Animations.Loading)) + val Loading: IconSource = IconSource("Loading", animation = Some(Animation( + Size2D(48, 32), + (0, 0.7f), + (1, 0.7f), + (2, 0.7f), + (3, 0.7f), + (4, 0.7f), + (5, 0.7f), + (6, 0.7f), + (7, 0.7f), + (8, 0.7f), + (9, 0.7f), + (10, 0.7f), + (11, 0.7f), + (12, 0.7f), + (13, 0.7f), + ))) val SettingsSystem: IconSource = IconSource("icons/SettingsSystem") val SettingsSound: IconSource = IconSource("icons/SettingsSound") @@ -168,4 +178,20 @@ object IconSource { val Guitar: IconSource = IconSource("icons/Guitar") val Keyboard: IconSource = IconSource("icons/Keyboard") val KeyboardOff: IconSource = IconSource("icons/KeyboardOff") + + // ----------------------- Node icons ----------------------- + + val NA: IconSource = IconSource("icons/NA") + + object Nodes { + object OcelotBlock { + val Default: IconSource = IconSource( + "nodes/ocelot-block/Default", + animation = Some(Animation(Size2D(16, 16), (0, 30f), (1, 5f), (2, 2f), (0, 20f), (3, 3f), (4, 2f))), + ) + + val Rx: IconSource = IconSource("nodes/ocelot-block/Rx") + val Tx: IconSource = IconSource("nodes/ocelot-block/Tx") + } + } } diff --git a/src/main/scala/ocelot/desktop/inventory/Items.scala b/src/main/scala/ocelot/desktop/inventory/Items.scala index a11be3a..09d85b2 100644 --- a/src/main/scala/ocelot/desktop/inventory/Items.scala +++ b/src/main/scala/ocelot/desktop/inventory/Items.scala @@ -105,7 +105,7 @@ object Items extends Logging { // Anyway we don't want to see its icon as default one in context menu registerArbitrary( "Memory", - IconSource.Memory(ExtendedTier.ThreeHalf), + IconSource.Items.Memory(ExtendedTier.ThreeHalf), (ExtendedTier.One to ExtendedTier.Creative).iterator .map { case ExtendedTier.Creative => new MagicalMemoryItem.Factory() diff --git a/src/main/scala/ocelot/desktop/inventory/item/ApuItem.scala b/src/main/scala/ocelot/desktop/inventory/item/ApuItem.scala index 341c4b9..7cb2c66 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/ApuItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/ApuItem.scala @@ -26,7 +26,7 @@ object ApuItem { // we keep the latter tier internally and increment it when dealing with the rest of the world override def tier: Option[Tier] = Some(_tier.saturatingAdd(1)) - override def icon: IconSource = IconSource.Apu(_tier) + override def icon: IconSource = IconSource.Items.Apu(_tier) override def build(): ApuItem = new ApuItem(new APU(_tier)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/ComponentBusItem.scala b/src/main/scala/ocelot/desktop/inventory/item/ComponentBusItem.scala index c6290da..c479186 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/ComponentBusItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/ComponentBusItem.scala @@ -34,7 +34,7 @@ object ComponentBusItem { override def tier: Option[Tier] = Some(_tier) - override def icon: IconSource = IconSource.ComponentBus(_tier) + override def icon: IconSource = IconSource.Items.ComponentBus(_tier) override def build(): ComponentBusItem = new ComponentBusItem(new ComponentBus(_tier)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/CpuItem.scala b/src/main/scala/ocelot/desktop/inventory/item/CpuItem.scala index cd2b57b..2901908 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/CpuItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/CpuItem.scala @@ -23,7 +23,7 @@ object CpuItem { override def tier: Option[Tier] = Some(_tier) - override def icon: IconSource = IconSource.Cpu(_tier) + override def icon: IconSource = IconSource.Items.Cpu(_tier) override def build(): CpuItem = new CpuItem(new CPU(_tier)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/DataCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/DataCardItem.scala index 4aa5696..9dc5512 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/DataCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/DataCardItem.scala @@ -14,7 +14,7 @@ object DataCardItem { abstract class Factory extends ItemFactory { override def name: String = s"Data Card (${tier.get.label})" - override def icon: IconSource = IconSource.DataCard(tier.get) + override def icon: IconSource = IconSource.Items.DataCard(tier.get) } class Tier1(val dataCard: DataCard.Tier1) extends DataCardItem { diff --git a/src/main/scala/ocelot/desktop/inventory/item/DiskDriveMountableItem.scala b/src/main/scala/ocelot/desktop/inventory/item/DiskDriveMountableItem.scala index 8ffabd0..701d171 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/DiskDriveMountableItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/DiskDriveMountableItem.scala @@ -1,6 +1,7 @@ package ocelot.desktop.inventory.item import ocelot.desktop.graphics.IconSource +import ocelot.desktop.inventory.traits.RackMountableItem import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer} import ocelot.desktop.util.DiskDriveAware import totoro.ocelot.brain.entity.{DiskDriveMountable, FloppyDiskDrive} @@ -26,7 +27,7 @@ object DiskDriveMountableItem { override def name: String = "Disk Drive" - override def icon: IconSource = IconSource.DiskDriveMountable + override def icon: IconSource = IconSource.Items.DiskDriveMountable override def build(): DiskDriveMountableItem = { val item = new DiskDriveMountableItem(new DiskDriveMountable()) diff --git a/src/main/scala/ocelot/desktop/inventory/item/EepromItem.scala b/src/main/scala/ocelot/desktop/inventory/item/EepromItem.scala index 9f32865..d469204 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/EepromItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/EepromItem.scala @@ -84,7 +84,7 @@ object EepromItem { override def tier: Option[Tier] = None - override def icon: IconSource = IconSource.Eeprom + override def icon: IconSource = IconSource.Items.Eeprom override def recoverers: Iterable[ItemRecoverer[_, _]] = Some(ItemRecoverer(new EepromItem(_))) } diff --git a/src/main/scala/ocelot/desktop/inventory/item/FloppyItem.scala b/src/main/scala/ocelot/desktop/inventory/item/FloppyItem.scala index a76da66..4ca145f 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/FloppyItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/FloppyItem.scala @@ -84,7 +84,7 @@ object FloppyItem { override def tier: Option[Tier] = None - override def icon: IconSource = IconSource.FloppyDisk(color) + override def icon: IconSource = IconSource.Items.FloppyDisk(color) override def recoverers: Iterable[ItemRecoverer[_, _]] = Some(ItemRecoverer(new FloppyItem(_))) } diff --git a/src/main/scala/ocelot/desktop/inventory/item/GraphicsCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/GraphicsCardItem.scala index 9d7aa19..5a8a8e1 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/GraphicsCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/GraphicsCardItem.scala @@ -21,7 +21,7 @@ object GraphicsCardItem { override def name: String = s"Graphics Card (${_tier.label})" override def tier: Option[Tier] = Some(_tier) - override def icon: IconSource = IconSource.GraphicsCard(_tier) + override def icon: IconSource = IconSource.Items.GraphicsCard(_tier) override def build(): GraphicsCardItem = new GraphicsCardItem(new GraphicsCard(_tier)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/HddItem.scala b/src/main/scala/ocelot/desktop/inventory/item/HddItem.scala index 62c8074..6da9467 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/HddItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/HddItem.scala @@ -76,7 +76,7 @@ object HddItem { override def tier: Option[Tier] = Some(_tier) - override def icon: IconSource = IconSource.HardDiskDrive(_tier) + override def icon: IconSource = IconSource.Items.HardDiskDrive(_tier) override def build(): HddItem = new HddItem( if (managed) Hdd(new HDDManaged(_tier)) else Hdd(new HDDUnmanaged(_tier)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/InternetCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/InternetCardItem.scala index 535dc56..47b92fc 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/InternetCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/InternetCardItem.scala @@ -24,7 +24,7 @@ object InternetCardItem { override def tier: Option[Tier] = Some(Tier.Two) - override def icon: IconSource = IconSource.InternetCard + override def icon: IconSource = IconSource.Items.InternetCard override def build(): InternetCardItem = new InternetCardItem(new InternetCard) diff --git a/src/main/scala/ocelot/desktop/inventory/item/LinkedCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/LinkedCardItem.scala index 18054b3..6076d4a 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/LinkedCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/LinkedCardItem.scala @@ -45,7 +45,7 @@ object LinkedCardItem { override def tier: Option[Tier] = Some(Tier.Three) - override def icon: IconSource = IconSource.LinkedCard + override def icon: IconSource = IconSource.Items.LinkedCard override def build(): LinkedCardItem = new LinkedCardItem(new LinkedCard) diff --git a/src/main/scala/ocelot/desktop/inventory/item/MagicalMemoryItem.scala b/src/main/scala/ocelot/desktop/inventory/item/MagicalMemoryItem.scala index ad6235f..c93394e 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/MagicalMemoryItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/MagicalMemoryItem.scala @@ -24,7 +24,7 @@ object MagicalMemoryItem { override def tier: Option[Tier] = Some(Tier.One) - override def icon: IconSource = IconSource.Memory(ExtendedTier.Creative) + override def icon: IconSource = IconSource.Items.Memory(ExtendedTier.Creative) override def build(): MagicalMemoryItem = new MagicalMemoryItem(new MagicalMemory()) diff --git a/src/main/scala/ocelot/desktop/inventory/item/MemoryItem.scala b/src/main/scala/ocelot/desktop/inventory/item/MemoryItem.scala index 0731a23..42e12d4 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/MemoryItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/MemoryItem.scala @@ -24,7 +24,7 @@ object MemoryItem { override def tier: Option[Tier] = Some(memoryTier.toTier) - override def icon: IconSource = IconSource.Memory(memoryTier) + override def icon: IconSource = IconSource.Items.Memory(memoryTier) override def build(): MemoryItem = new MemoryItem(new Memory(memoryTier)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/NetworkCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/NetworkCardItem.scala index 1f3d4bc..b35eea6 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/NetworkCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/NetworkCardItem.scala @@ -22,7 +22,7 @@ object NetworkCardItem { override def name: String = "Network Card" override def tier: Option[Tier] = Some(Tier.One) - override def icon: IconSource = IconSource.NetworkCard + override def icon: IconSource = IconSource.Items.NetworkCard override def build(): NetworkCardItem = new NetworkCardItem(new NetworkCard) diff --git a/src/main/scala/ocelot/desktop/inventory/item/OcelotCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/OcelotCardItem.scala index 1e9bffa..fe25e64 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/OcelotCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/OcelotCardItem.scala @@ -3,53 +3,27 @@ package ocelot.desktop.inventory.item import ocelot.desktop.ColorScheme import ocelot.desktop.color.Color import ocelot.desktop.entity.OcelotCard +import ocelot.desktop.entity.traits.OcelotInterface import ocelot.desktop.graphics.IconSource -import ocelot.desktop.inventory.item.OcelotCardItem.{EntriesTag, EntryKindRx, EntryKindTag, EntryKindTx, EntryMessageTag, MessageLimitTag, MessagesTag} import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} -import ocelot.desktop.ui.event.BrainEvent -import ocelot.desktop.ui.widget.LogWidget.LogEntry -import ocelot.desktop.ui.widget.card.OcelotCardWindow import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} -import ocelot.desktop.ui.widget.window.Windowed -import ocelot.desktop.util.Logging -import totoro.ocelot.brain.nbt.ExtendedNBT.extendNBTTagList -import totoro.ocelot.brain.nbt.{NBT, NBTBase, NBTTagCompound, NBTTagString} +import ocelot.desktop.util.{Logging, OcelotInterfaceLogStorage} import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier.Tier -import scala.collection.mutable -import scala.jdk.CollectionConverters.BufferHasAsJava - class OcelotCardItem(val ocelotCard: OcelotCard) extends Item with ComponentItem + with OcelotInterfaceLogStorage with PersistableItem with CardItem - with Windowed[OcelotCardWindow] with Logging { - private var _messageLimit: Int = 1000 - - // NOTE: access must be synchronized! - // ocelot.log() is a direct method, so it may push events even if the tick lock is not acquired - private val _entries = mutable.ArrayDeque.empty[LogEntry] - - eventHandlers += { - case BrainEvent(OcelotCard.LogEvent.Clear(_)) => - clear() - - case BrainEvent(OcelotCard.LogEvent.CardToUser(_, message)) => - addEntry(LogEntry.Rx(message)) - - case BrainEvent(OcelotCard.LogEvent.UserToCard(_, message)) => - addEntry(LogEntry.Tx(message)) - } - - override def createWindow(): OcelotCardWindow = new OcelotCardWindow(this) - override def component: OcelotCard = ocelotCard + override def ocelotInterface: OcelotInterface = ocelotCard + override def tooltipNameColor: Color = ColorScheme("OcelotCardTooltip") override def fillRmbMenu(menu: ContextMenu): Unit = { @@ -62,124 +36,10 @@ class OcelotCardItem(val ocelotCard: OcelotCard) super.fillRmbMenu(menu) } - private def loadEntry(nbt: NBTTagCompound): Either[String, LogEntry] = { - nbt.getString(EntryKindTag) match { - case EntryKindRx => Right(LogEntry.Rx(nbt.getString(EntryMessageTag))) - case EntryKindTx => Right(LogEntry.Tx(nbt.getString(EntryMessageTag))) - - case "" => Left("entry kind not set") - case k => Left(s"unknown entry kind: $k") - } - } - - private def saveEntry(entry: LogEntry): NBTTagCompound = { - val result = new NBTTagCompound() - - entry match { - case LogEntry.Rx(message) => - result.setString(EntryKindTag, EntryKindRx) - result.setString(EntryMessageTag, message) - - case LogEntry.Tx(message) => - result.setString(EntryKindTag, EntryKindTx) - result.setString(EntryMessageTag, message) - } - - result - } - - override def load(nbt: NBTTagCompound): Unit = { - super.load(nbt) - - clear() - - if (nbt.hasKey(MessageLimitTag)) { - messageLimit = nbt.getInteger(MessageLimitTag) - } - - val entries = if (nbt.hasKey(EntriesTag)) { - nbt.getTagList(EntriesTag, NBT.TAG_COMPOUND).iterator[NBTTagCompound].zipWithIndex.flatMap { - case (entryNbt, idx) => - loadEntry(entryNbt) match { - case Left(err) => - logger.warn(s"Could not restore log entry (idx $idx) of ocelot card ${component.node.address}: $err") - None - - case Right(entry) => Some(entry) - } - } - } else { - // old save format: plain messages - nbt - .getTagList(MessagesTag, NBT.TAG_STRING) - .iterator[NBTTagString] - .map(entryNbt => LogEntry.Rx(entryNbt.getString)) - } - - addEntries(entries.toSeq) - } - - override def save(nbt: NBTTagCompound): Unit = _entries.synchronized { - super.save(nbt) - - nbt.setTagList(EntriesTag, _entries.map(saveEntry(_).asInstanceOf[NBTBase]).asJava) - nbt.setInteger(MessageLimitTag, _messageLimit) - } - override def factory: ItemFactory = OcelotCardItem.Factory - - def messageLimit: Int = _messageLimit - - def messageLimit_=(limit: Int): Unit = _entries.synchronized { - require(limit > 0) - ensureFreeSpace(_entries.length - limit) - _messageLimit = limit - } - - def entryCount: Int = _entries.synchronized { - _entries.length - } - - def clear(): Unit = _entries.synchronized { - val count = _entries.length - _entries.clear() - window.onMessagesRemoved(count) - } - - private def addEntry(entry: LogEntry): Unit = _entries.synchronized { - ensureFreeSpace(1) - _entries += entry - window.onMessagesAdded(Some(entry)) - } - - private def addEntries(entries: Seq[LogEntry]): Unit = _entries.synchronized { - ensureFreeSpace(entries.length) - val prevCount = _entries.length - _entries ++= entries.view.takeRight(messageLimit) - window.onMessagesAdded(_entries.view.takeRight(_entries.length - prevCount)) - } - - private def ensureFreeSpace(n: Int): Unit = _entries.synchronized { - val prevCount = _entries.length - _entries.takeRightInPlace(messageLimit - n) - val removedCount = prevCount - _entries.length - - if (removedCount > 0) { - window.onMessagesRemoved(removedCount) - } - } } object OcelotCardItem { - val MessagesTag = "messages" - val EntriesTag = "entries" - val MessageLimitTag = "limit" - - val EntryKindTag = "kind" - val EntryKindRx = "rx" - val EntryKindTx = "tx" - val EntryMessageTag = "msg" - object Factory extends ItemFactory { override type I = OcelotCardItem @@ -189,7 +49,7 @@ object OcelotCardItem { override def tier: Option[Tier] = Some(Tier.One) - override def icon: IconSource = IconSource.OcelotCard + override def icon: IconSource = IconSource.Items.OcelotCard override def build(): OcelotCardItem = new OcelotCardItem(new OcelotCard) diff --git a/src/main/scala/ocelot/desktop/inventory/item/RedstoneCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/RedstoneCardItem.scala index f0d4136..ac144ee 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/RedstoneCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/RedstoneCardItem.scala @@ -21,7 +21,7 @@ object RedstoneCardItem { abstract class Factory extends ItemFactory { override def name: String = s"Redstone Card (${tier.get.label})" - override def icon: IconSource = IconSource.RedstoneCard(tier.get) + override def icon: IconSource = IconSource.Items.RedstoneCard(tier.get) } class Tier1(val redstoneCard: Redstone.Tier1) extends RedstoneCardItem { diff --git a/src/main/scala/ocelot/desktop/inventory/item/SelfDestructingCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/SelfDestructingCardItem.scala index 362c2af..82261b6 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/SelfDestructingCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/SelfDestructingCardItem.scala @@ -29,7 +29,7 @@ object SelfDestructingCardItem { override def tier: Option[Tier] = Some(Tier.Two) - override def icon: IconSource = IconSource.SelfDestructingCard + override def icon: IconSource = IconSource.Items.SelfDestructingCard override def build(): SelfDestructingCardItem = new SelfDestructingCardItem(new SelfDestructingCard) diff --git a/src/main/scala/ocelot/desktop/inventory/item/ServerItem.scala b/src/main/scala/ocelot/desktop/inventory/item/ServerItem.scala index ce5120b..6511a8a 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/ServerItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/ServerItem.scala @@ -1,6 +1,7 @@ package ocelot.desktop.inventory.item import ocelot.desktop.graphics.IconSource +import ocelot.desktop.inventory.traits.RackMountableItem import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer} import ocelot.desktop.ui.widget.slot._ import ocelot.desktop.util.ComputerType.ComputerType @@ -106,7 +107,7 @@ object ServerItem { override def tier: Option[Tier] = Some(_tier) - override def icon: IconSource = IconSource.Server(_tier) + override def icon: IconSource = IconSource.Items.Server(_tier) override def build(): ServerItem = { val item = new ServerItem(new Server(_tier)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/SoundCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/SoundCardItem.scala index 567ab93..4e43eca 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/SoundCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/SoundCardItem.scala @@ -45,7 +45,7 @@ object SoundCardItem { override def tier: Option[Tier] = Some(Tier.Two) - override def icon: IconSource = IconSource.SoundCard + override def icon: IconSource = IconSource.Items.SoundCard override def build(): SoundCardItem = new SoundCardItem(new SoundCard) diff --git a/src/main/scala/ocelot/desktop/inventory/item/TapeItem.scala b/src/main/scala/ocelot/desktop/inventory/item/TapeItem.scala index 15072d5..4e129e6 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/TapeItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/TapeItem.scala @@ -55,7 +55,7 @@ object TapeItem { override def tier: Option[Tier] = None - override def icon: IconSource = IconSource.Tape(kind) + override def icon: IconSource = IconSource.Items.Tape(kind) override def build(): TapeItem = new TapeItem(new Tape(kind)) diff --git a/src/main/scala/ocelot/desktop/inventory/item/WirelessNetworkCardItem.scala b/src/main/scala/ocelot/desktop/inventory/item/WirelessNetworkCardItem.scala index 487478a..ae9e3b1 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/WirelessNetworkCardItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/item/WirelessNetworkCardItem.scala @@ -14,7 +14,7 @@ object WirelessNetworkCardItem { abstract class Factory extends ItemFactory { override def name: String = s"Wireless Net. Card (${tier.get.label})" - override def icon: IconSource = IconSource.WirelessNetworkCard(tier.get) + override def icon: IconSource = IconSource.Items.WirelessNetworkCard(tier.get) } class Tier1(override val card: WirelessNetworkCard.Tier1) extends WirelessNetworkCardItem(card) { diff --git a/src/main/scala/ocelot/desktop/inventory/item/RackMountableItem.scala b/src/main/scala/ocelot/desktop/inventory/traits/RackMountableItem.scala similarity index 86% rename from src/main/scala/ocelot/desktop/inventory/item/RackMountableItem.scala rename to src/main/scala/ocelot/desktop/inventory/traits/RackMountableItem.scala index 3982698..b57bb32 100644 --- a/src/main/scala/ocelot/desktop/inventory/item/RackMountableItem.scala +++ b/src/main/scala/ocelot/desktop/inventory/traits/RackMountableItem.scala @@ -1,7 +1,6 @@ -package ocelot.desktop.inventory.item +package ocelot.desktop.inventory.traits import ocelot.desktop.inventory.Item -import ocelot.desktop.inventory.traits.ComponentItem import ocelot.desktop.node.nodes.RackNode import ocelot.desktop.ui.widget.contextmenu.ContextMenu import totoro.ocelot.brain.entity.result diff --git a/src/main/scala/ocelot/desktop/node/ComputerAwareNode.scala b/src/main/scala/ocelot/desktop/node/ComputerAwareNode.scala index e01c0e3..0207c17 100644 --- a/src/main/scala/ocelot/desktop/node/ComputerAwareNode.scala +++ b/src/main/scala/ocelot/desktop/node/ComputerAwareNode.scala @@ -1,8 +1,7 @@ package ocelot.desktop.node +import ocelot.desktop.OcelotDesktop import ocelot.desktop.audio._ -import ocelot.desktop.entity.OcelotCard -import ocelot.desktop.geometry.FloatUtils.ExtendedFloat import ocelot.desktop.geometry.Vector2D import ocelot.desktop.graphics.Graphics import ocelot.desktop.inventory.SyncedInventory @@ -13,20 +12,18 @@ import ocelot.desktop.ui.event.BrainEvent import ocelot.desktop.ui.event.handlers.DiskActivityHandler import ocelot.desktop.ui.widget.ComputerErrorMessageLabel import ocelot.desktop.util.Messages -import ocelot.desktop.{ColorScheme, OcelotDesktop} import totoro.ocelot.brain.Settings import totoro.ocelot.brain.entity.traits.{Entity, Environment, WorkspaceAware} import totoro.ocelot.brain.event._ import java.util.Calendar -import scala.collection.mutable import scala.collection.mutable.ArrayBuffer -import scala.util.Random abstract class ComputerAwareNode(entity: Entity with Environment with WorkspaceAware) extends EntityNode(entity) with SyncedInventory with DiskActivityHandler + with OcelotLogParticleNode with ShiftClickNode { // access should be synchronized because messages are added in the update thread @@ -36,20 +33,6 @@ abstract class ComputerAwareNode(entity: Entity with Environment with WorkspaceA messages += ((0f, message)) } - private case class LogParticle( - var time: Float = -LogParticleGrow, - angle: Float = Random.between(0f, 2 * math.Pi.toFloat * LogParticleMaxAngle) - ) - - // access should be synchronized because log particles are added in the update thread - private val logParticles = mutable.ArrayDeque.empty[LogParticle] - - private def addLogParticle(): Unit = logParticles.synchronized { - if (logParticles.length < MaxLogParticles) { - logParticles += LogParticle() - } - } - private lazy val soundCardSounds: (SoundStream, SoundSource) = Audio.newStream(SoundCategory.Records) private def soundCardStream: SoundStream = soundCardSounds._1 private def soundCardSource: SoundSource = soundCardSounds._2 @@ -84,17 +67,9 @@ abstract class ComputerAwareNode(entity: Entity with Environment with WorkspaceA SoundSource.MinecraftExplosion.play() destroy() }) - - case BrainEvent(OcelotCard.LogEvent.CardToUser(_, _)) => - addLogParticle() } override def update(): Unit = { - logParticles.synchronized { - logParticles.foreach(particle => particle.time += LogParticleMoveSpeed * UiHandler.dt) - logParticles.filterInPlace(_.time <= 1f) - } - messages.synchronized { messages.mapInPlace { case (t, message) => (t + ErrorMessageMoveSpeed * UiHandler.dt, message) } messages.filterInPlace(_._1 <= 1f) @@ -111,28 +86,9 @@ abstract class ComputerAwareNode(entity: Entity with Environment with WorkspaceA } } - private def drawLogParticles(g: Graphics): Unit = logParticles.synchronized { - for (particle <- logParticles) { - val size = (1 + particle.time / LogParticleGrow).clamp() * LogParticleSize - val offset = particle.time.clamp() * LogParticleMoveDistance - val alpha = 1 - particle.time.clamp() - - val r1 = (bounds.w max bounds.h) / math.sqrt(2) + offset + LogParticlePadding - val r2 = r1 + size - - for (i <- 0 until LogParticleCount) { - val angle = particle.angle + (2 * math.Pi).toFloat * i / LogParticleCount - val v = Vector2D.unit(angle) - val p1 = v * r1 + bounds.center - val p2 = v * r2 + bounds.center - g.line(p1, p2, 1f, ColorScheme("LogParticle").mapA(_ => alpha)) - } - } - } - override def drawParticles(g: Graphics): Unit = { + super.drawParticles(g) drawMessageParticles(g) - drawLogParticles(g) } protected def drawOverlay(g: Graphics): Unit = { @@ -162,15 +118,6 @@ object ComputerAwareNode { private val MaxErrorMessageDistance: Float = 50f private val ErrorMessageMoveSpeed: Float = 0.5f - private val MaxLogParticles: Int = 15 - private val LogParticleMaxAngle: Float = 0.25f - private val LogParticleCount: Int = 12 - private val LogParticleGrow: Float = 0.25f - private val LogParticlePadding: Float = 2f - private val LogParticleSize: Float = 10f - private val LogParticleMoveSpeed: Float = 1f - private val LogParticleMoveDistance: Float = 20f - private var HolidaySprite: Option[String] = None { diff --git a/src/main/scala/ocelot/desktop/node/Node.scala b/src/main/scala/ocelot/desktop/node/Node.scala index f29c10a..d36de0e 100644 --- a/src/main/scala/ocelot/desktop/node/Node.scala +++ b/src/main/scala/ocelot/desktop/node/Node.scala @@ -3,6 +3,7 @@ package ocelot.desktop.node import ocelot.desktop.audio.SoundSource import ocelot.desktop.color.{Color, RGBAColor} import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} +import ocelot.desktop.graphics.IconSource.Animation import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.node.Node._ import ocelot.desktop.ui.event.handlers.{ClickHandler, DragHandler, HoverHandler} @@ -116,8 +117,11 @@ abstract class Node extends Widget with DragHandler with ClickHandler with Hover super.dispose() } + // TODO: remove this (subsumed by iconSource) def icon: String = "icons/NA" + def iconSource: IconSource = IconSource(icon) + def iconColor: Color = RGBAColor(255, 255, 255) def ports: Array[NodePort] = Array() @@ -257,12 +261,13 @@ abstract class Node extends Widget with DragHandler with ClickHandler with Hover drawHighlight(g) g.sprite( - icon, + iconSource.path, position. x + HighlightThickness, position.y + HighlightThickness, size.width - HighlightThickness * 2, size.height - HighlightThickness * 2, - iconColor + iconColor, + iconSource.animation, ) } diff --git a/src/main/scala/ocelot/desktop/node/NodeRegistry.scala b/src/main/scala/ocelot/desktop/node/NodeRegistry.scala index d556bcc..a15dad3 100644 --- a/src/main/scala/ocelot/desktop/node/NodeRegistry.scala +++ b/src/main/scala/ocelot/desktop/node/NodeRegistry.scala @@ -1,6 +1,7 @@ package ocelot.desktop.node -import ocelot.desktop.entity.{Camera, OpenFMRadio} +import ocelot.desktop.entity.{Camera, OcelotBlock, OpenFMRadio} +import ocelot.desktop.graphics.IconSource import ocelot.desktop.node.nodes._ import totoro.ocelot.brain.entity.{Cable, Case, ColorfulLamp, FloppyDiskDrive, HologramProjector, IronNoteBlock, Microcontroller, NoteBlock, Rack, Raid, Relay, Screen, TapeDrive} import totoro.ocelot.brain.util.Tier @@ -100,4 +101,12 @@ object NodeRegistry { addType(NodeType("Tape Drive", "nodes/TapeDrive", None) { new TapeDriveNode(new TapeDrive) }) + + // ------------------------------ Custom nodes ------------------------------ + + nextGroup("Custom") + + addType(NodeType("Ocelot Block", IconSource.Nodes.OcelotBlock.Default, None) { + new OcelotBlockNode(new OcelotBlock) + }) } diff --git a/src/main/scala/ocelot/desktop/node/NodeType.scala b/src/main/scala/ocelot/desktop/node/NodeType.scala index 2e0f22c..6570b1a 100644 --- a/src/main/scala/ocelot/desktop/node/NodeType.scala +++ b/src/main/scala/ocelot/desktop/node/NodeType.scala @@ -1,17 +1,27 @@ package ocelot.desktop.node +import ocelot.desktop.graphics.IconSource import totoro.ocelot.brain.util.Tier.Tier -class NodeType(val name: String, val icon: String, val tier: Option[Tier], factory: => Node) extends Ordered[NodeType] { +class NodeType(val name: String, val icon: IconSource, val tier: Option[Tier], factory: => Node) + extends Ordered[NodeType] { def make(): Node = factory override def compare(that: NodeType): Int = this.name.compare(that.name) } object NodeType { - def apply(name: String, icon: String, tier: Tier)(factory: => Node): NodeType = + // TODO: remove this + def apply(name: String, icon: IconSource, tier: Tier)(factory: => Node): NodeType = new NodeType(name, icon, Some(tier), factory) - def apply(name: String, icon: String, tier: Option[Tier])(factory: => Node): NodeType = + def apply(name: String, icon: String, tier: Tier)(factory: => Node): NodeType = + new NodeType(name, IconSource(icon), Some(tier), factory) + + // TODO: remove this + def apply(name: String, icon: IconSource, tier: Option[Tier])(factory: => Node): NodeType = new NodeType(name, icon, tier, factory) + + def apply(name: String, icon: String, tier: Option[Tier])(factory: => Node): NodeType = + new NodeType(name, IconSource(icon), tier, factory) } diff --git a/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala b/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala index eef2e4c..7e21c66 100644 --- a/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala +++ b/src/main/scala/ocelot/desktop/node/NodeTypeWidget.scala @@ -39,12 +39,13 @@ class NodeTypeWidget(val nodeType: NodeType) extends Widget with ClickHandler wi val size = Spritesheet.spriteSize(nodeType.icon) * 4 g.sprite( - nodeType.icon, + nodeType.icon.path, position.x + Size / 2 - size.width / 2, position.y + Size / 2 - size.height / 2, size.width, size.height, - nodeType.tier.map(TierColor.get).getOrElse(Color.White) + nodeType.tier.map(TierColor.get).getOrElse(Color.White), + nodeType.icon.animation, ) } diff --git a/src/main/scala/ocelot/desktop/node/OcelotLogParticleNode.scala b/src/main/scala/ocelot/desktop/node/OcelotLogParticleNode.scala new file mode 100644 index 0000000..2f0b259 --- /dev/null +++ b/src/main/scala/ocelot/desktop/node/OcelotLogParticleNode.scala @@ -0,0 +1,80 @@ +package ocelot.desktop.node + +import ocelot.desktop.ColorScheme +import ocelot.desktop.entity.traits.OcelotInterface +import ocelot.desktop.geometry.FloatUtils.ExtendedFloat +import ocelot.desktop.geometry.Vector2D +import ocelot.desktop.graphics.Graphics +import ocelot.desktop.node.OcelotLogParticleNode._ +import ocelot.desktop.ui.UiHandler +import ocelot.desktop.ui.event.BrainEvent + +import scala.collection.mutable +import scala.util.Random + +trait OcelotLogParticleNode extends Node { + private case class LogParticle( + var time: Float = -LogParticleGrow, + angle: Float = Random.between(0f, 2 * math.Pi.toFloat * LogParticleMaxAngle) + ) + + // access should be synchronized because log particles are added in the update thread + private val logParticles = mutable.ArrayDeque.empty[LogParticle] + + private def addLogParticle(): Unit = logParticles.synchronized { + if (logParticles.length < MaxLogParticles) { + logParticles += LogParticle() + } + } + + eventHandlers += { + case BrainEvent(OcelotInterface.LogEvent.CardToUser(_, _)) => + addLogParticle() + } + + override def update(): Unit = { + super.update() + + logParticles.synchronized { + logParticles.foreach(particle => particle.time += LogParticleMoveSpeed * UiHandler.dt) + logParticles.filterInPlace(_.time <= 1f) + } + } + + private def drawLogParticles(g: Graphics): Unit = logParticles.synchronized { + for (particle <- logParticles) { + val size = (1 + particle.time / LogParticleGrow).clamp() * LogParticleSize + val offset = particle.time.clamp() * LogParticleMoveDistance + val alpha = 1 - particle.time.clamp() + + val r1 = (bounds.w max bounds.h) / math.sqrt(2) + offset + LogParticlePadding + val r2 = r1 + size + + for (i <- 0 until LogParticleCount) { + val angle = particle.angle + (2 * math.Pi).toFloat * i / LogParticleCount + val v = Vector2D.unit(angle) + val p1 = v * r1 + bounds.center + val p2 = v * r2 + bounds.center + g.line(p1, p2, 1f, ColorScheme("LogParticle").mapA(_ => alpha)) + } + } + } + + override def drawParticles(g: Graphics): Unit = { + super.drawParticles(g) + drawLogParticles(g) + } +} + +object OcelotLogParticleNode { + private val MaxLogParticles: Int = 15 + private val LogParticleMaxAngle: Float = 0.25f + private val LogParticleCount: Int = 12 + private val LogParticleGrow: Float = 0.25f + private val LogParticlePadding: Float = 2f + private val LogParticleSize: Float = 10f + private val LogParticleMoveSpeed: Float = 1f + private val LogParticleMoveDistance: Float = 20f +} + + diff --git a/src/main/scala/ocelot/desktop/node/nodes/OcelotBlockNode.scala b/src/main/scala/ocelot/desktop/node/nodes/OcelotBlockNode.scala new file mode 100644 index 0000000..8ac98dd --- /dev/null +++ b/src/main/scala/ocelot/desktop/node/nodes/OcelotBlockNode.scala @@ -0,0 +1,83 @@ +package ocelot.desktop.node.nodes + +import ocelot.desktop.color.RGBAColorNorm +import ocelot.desktop.entity.OcelotBlock +import ocelot.desktop.entity.traits.OcelotInterface +import ocelot.desktop.geometry.FloatUtils.ExtendedFloat +import ocelot.desktop.graphics.{Graphics, IconSource} +import ocelot.desktop.node.Node.HighlightThickness +import ocelot.desktop.node.nodes.OcelotBlockNode.ActivityFadeOutMs +import ocelot.desktop.node.{EntityNode, LabeledEntityNode, OcelotLogParticleNode, WindowedNode} +import ocelot.desktop.ui.widget.LogWidget +import ocelot.desktop.ui.widget.LogWidget.LogEntry +import ocelot.desktop.util.OcelotInterfaceLogStorage +import ocelot.desktop.windows.OcelotInterfaceWindow + +class OcelotBlockNode(val ocelot: OcelotBlock) + extends EntityNode(ocelot) + with LabeledEntityNode + with OcelotLogParticleNode + with OcelotInterfaceLogStorage + with WindowedNode[OcelotInterfaceWindow] { + + override def name: String = "Ocelot Block" + + override def iconSource: IconSource = IconSource.Nodes.OcelotBlock.Default + + override def ocelotInterface: OcelotInterface = ocelot + + private var lastRx: Long = -1L + private var lastTx: Long = -1L + + override protected def onMessagesAdded(entries: => Iterable[LogWidget.LogEntry]): Unit = { + super.onMessagesAdded(entries) + + var hasRx = false + var hasTx = false + + for (entry <- entries.iterator.takeWhile(_ => !hasRx || !hasTx)) { + entry match { + case _: LogEntry.Rx => hasRx = true + case _: LogEntry.Tx => hasTx = true + } + } + + val t = System.currentTimeMillis() + + if (hasRx) { + lastRx = t + } + + if (hasTx) { + lastTx = t + } + } + + override def draw(g: Graphics): Unit = { + super.draw(g) + + val t = System.currentTimeMillis() + drawActivity(g, IconSource.Nodes.OcelotBlock.Rx, lastRx, t) + drawActivity(g, IconSource.Nodes.OcelotBlock.Tx, lastTx, t) + } + + private def drawActivity(g: Graphics, icon: IconSource, lastActivity: Long, currentTime: Long): Unit = { + val alpha = (1 - (currentTime - lastActivity) / ActivityFadeOutMs).clamp() + + if (alpha > 0) { + g.sprite( + icon.path, + position.x + HighlightThickness, + position.y + HighlightThickness, + size.width - HighlightThickness * 2, + size.height - HighlightThickness * 2, + RGBAColorNorm(1f, 1f, 1f, alpha), + icon.animation, + ) + } + } +} + +object OcelotBlockNode { + private val ActivityFadeOutMs: Float = 300f +} diff --git a/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala b/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala index da7e58b..087cb2f 100644 --- a/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala +++ b/src/main/scala/ocelot/desktop/node/nodes/RackNode.scala @@ -3,7 +3,8 @@ package ocelot.desktop.node.nodes import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} import ocelot.desktop.graphics.{Graphics, IconSource} import ocelot.desktop.inventory.Item -import ocelot.desktop.inventory.item.{DiskDriveMountableItem, RackMountableItem, ServerItem} +import ocelot.desktop.inventory.item.{DiskDriveMountableItem, ServerItem} +import ocelot.desktop.inventory.traits.RackMountableItem import ocelot.desktop.node.Node.{HighlightThickness, NoHighlightSize, Size, TexelCount} import ocelot.desktop.node.{ComputerAwareNode, NodePort, WindowedNode} import ocelot.desktop.ui.event.{BrainEvent, ClickEvent} diff --git a/src/main/scala/ocelot/desktop/ui/widget/DiskEditWindow.scala b/src/main/scala/ocelot/desktop/ui/widget/DiskEditWindow.scala index 0638eae..706e37b 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/DiskEditWindow.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/DiskEditWindow.scala @@ -79,7 +79,7 @@ class DiskEditWindow(item: DiskItem) extends PanelWindow { for (dyeColor <- row) { def isColorSelected: Boolean = dyeColor == item.color.get - val floppyIcon = IconSource.FloppyDisk(dyeColor).path + val floppyIcon = IconSource.Items.FloppyDisk(dyeColor).path children :+= new IconButton( floppyIcon, floppyIcon, diff --git a/src/main/scala/ocelot/desktop/ui/widget/slot/RackMountableSlotWidget.scala b/src/main/scala/ocelot/desktop/ui/widget/slot/RackMountableSlotWidget.scala index 98d2e0b..493dc67 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/slot/RackMountableSlotWidget.scala +++ b/src/main/scala/ocelot/desktop/ui/widget/slot/RackMountableSlotWidget.scala @@ -2,7 +2,8 @@ package ocelot.desktop.ui.widget.slot import ocelot.desktop.graphics.IconSource import ocelot.desktop.inventory.Inventory -import ocelot.desktop.inventory.item.{RackMountableItem, ServerItem} +import ocelot.desktop.inventory.item.ServerItem +import ocelot.desktop.inventory.traits.RackMountableItem class RackMountableSlotWidget(slot: Inventory#Slot) extends SlotWidget[RackMountableItem](slot) diff --git a/src/main/scala/ocelot/desktop/util/OcelotInterfaceLogStorage.scala b/src/main/scala/ocelot/desktop/util/OcelotInterfaceLogStorage.scala new file mode 100644 index 0000000..41f7aab --- /dev/null +++ b/src/main/scala/ocelot/desktop/util/OcelotInterfaceLogStorage.scala @@ -0,0 +1,167 @@ +package ocelot.desktop.util + +import ocelot.desktop.entity.traits.OcelotInterface +import ocelot.desktop.ui.event.{BrainEvent, EventAware} +import ocelot.desktop.ui.widget.LogWidget.LogEntry +import ocelot.desktop.ui.widget.window.Windowed +import ocelot.desktop.util.OcelotInterfaceLogStorage._ +import ocelot.desktop.windows.OcelotInterfaceWindow +import totoro.ocelot.brain.nbt.ExtendedNBT.extendNBTTagList +import totoro.ocelot.brain.nbt.{NBT, NBTBase, NBTTagCompound, NBTTagString} + +import scala.collection.mutable +import scala.jdk.CollectionConverters.BufferHasAsJava + +trait OcelotInterfaceLogStorage + extends EventAware + with Persistable + with Windowed[OcelotInterfaceWindow] + with Logging { + + def ocelotInterface: OcelotInterface + + def name: String + + override def createWindow(): OcelotInterfaceWindow = new OcelotInterfaceWindow(this) + + private var _messageLimit: Int = 1000 + + // NOTE: access must be synchronized! + // ocelot.log() is a direct method, so it may push events even if the tick lock is not acquired + private val _entries = mutable.ArrayDeque.empty[LogEntry] + + eventHandlers += { + case BrainEvent(OcelotInterface.LogEvent.Clear(_)) => + clear() + + case BrainEvent(OcelotInterface.LogEvent.CardToUser(_, message)) => + addEntry(LogEntry.Rx(message)) + + case BrainEvent(OcelotInterface.LogEvent.UserToCard(_, message)) => + addEntry(LogEntry.Tx(message)) + } + + private def loadEntry(nbt: NBTTagCompound): Either[String, LogEntry] = { + nbt.getString(EntryKindTag) match { + case EntryKindRx => Right(LogEntry.Rx(nbt.getString(EntryMessageTag))) + case EntryKindTx => Right(LogEntry.Tx(nbt.getString(EntryMessageTag))) + + case "" => Left("entry kind not set") + case k => Left(s"unknown entry kind: $k") + } + } + + private def saveEntry(entry: LogEntry): NBTTagCompound = { + val result = new NBTTagCompound() + + entry match { + case LogEntry.Rx(message) => + result.setString(EntryKindTag, EntryKindRx) + result.setString(EntryMessageTag, message) + + case LogEntry.Tx(message) => + result.setString(EntryKindTag, EntryKindTx) + result.setString(EntryMessageTag, message) + } + + result + } + + override def load(nbt: NBTTagCompound): Unit = { + super.load(nbt) + + clear() + + if (nbt.hasKey(MessageLimitTag)) { + messageLimit = nbt.getInteger(MessageLimitTag) + } + + val entries = if (nbt.hasKey(EntriesTag)) { + nbt.getTagList(EntriesTag, NBT.TAG_COMPOUND).iterator[NBTTagCompound].zipWithIndex.flatMap { + case (entryNbt, idx) => + loadEntry(entryNbt) match { + case Left(err) => + logger.warn( + s"Could not restore log entry (idx $idx) of ocelot interface ${ocelotInterface.node.address}:" + + s" $err" + ) + + None + + case Right(entry) => Some(entry) + } + } + } else { + // old save format: plain messages + nbt + .getTagList(MessagesTag, NBT.TAG_STRING) + .iterator[NBTTagString] + .map(entryNbt => LogEntry.Rx(entryNbt.getString)) + } + + addEntries(entries.toSeq) + } + + override def save(nbt: NBTTagCompound): Unit = _entries.synchronized { + super.save(nbt) + + nbt.setTagList(EntriesTag, _entries.map(saveEntry(_).asInstanceOf[NBTBase]).asJava) + nbt.setInteger(MessageLimitTag, _messageLimit) + } + + def messageLimit: Int = _messageLimit + + def messageLimit_=(limit: Int): Unit = _entries.synchronized { + require(limit > 0) + ensureFreeSpace(_entries.length - limit) + _messageLimit = limit + } + + def entryCount: Int = _entries.synchronized { + _entries.length + } + + def clear(): Unit = _entries.synchronized { + val count = _entries.length + _entries.clear() + window.onMessagesRemoved(count) + } + + private def addEntry(entry: LogEntry): Unit = _entries.synchronized { + ensureFreeSpace(1) + _entries += entry + onMessagesAdded(Some(entry)) + } + + private def addEntries(entries: Seq[LogEntry]): Unit = _entries.synchronized { + ensureFreeSpace(entries.length) + val prevCount = _entries.length + _entries ++= entries.view.takeRight(messageLimit) + onMessagesAdded(_entries.view.takeRight(_entries.length - prevCount)) + } + + private def ensureFreeSpace(n: Int): Unit = _entries.synchronized { + val prevCount = _entries.length + _entries.takeRightInPlace(messageLimit - n) + val removedCount = prevCount - _entries.length + + if (removedCount > 0) { + window.onMessagesRemoved(removedCount) + } + } + + protected def onMessagesAdded(entries: => Iterable[LogEntry]): Unit = { + window.onMessagesAdded(entries) + } +} + +object OcelotInterfaceLogStorage { + private val MessagesTag = "messages" + private val EntriesTag = "entries" + private val MessageLimitTag = "limit" + + private val EntryKindTag = "kind" + private val EntryKindRx = "rx" + private val EntryKindTx = "tx" + private val EntryMessageTag = "msg" +} diff --git a/src/main/scala/ocelot/desktop/util/Spritesheet.scala b/src/main/scala/ocelot/desktop/util/Spritesheet.scala index 042e529..9c425b3 100644 --- a/src/main/scala/ocelot/desktop/util/Spritesheet.scala +++ b/src/main/scala/ocelot/desktop/util/Spritesheet.scala @@ -1,7 +1,7 @@ package ocelot.desktop.util import ocelot.desktop.geometry.{Rect2D, Size2D} -import ocelot.desktop.graphics.Texture +import ocelot.desktop.graphics.{IconSource, Texture} import javax.imageio.ImageIO import scala.collection.mutable @@ -15,6 +15,20 @@ object Spritesheet extends Resource with Logging { def spriteSize(sprite: String): Size2D = sprites(sprite).size * resolution + def spriteSize(iconSource: IconSource): Size2D = iconSource.animation match { + case Some(animation) => + animation.frameSize match { + case Some(size) => size + + case None => + val size = spriteSize(iconSource.path) + + Size2D(size.width, size.width) + } + + case None => spriteSize(iconSource.path) + } + def load(): Unit = { logger.info("Loading sprites") diff --git a/src/main/scala/ocelot/desktop/ui/widget/card/OcelotCardWindow.scala b/src/main/scala/ocelot/desktop/windows/OcelotInterfaceWindow.scala similarity index 81% rename from src/main/scala/ocelot/desktop/ui/widget/card/OcelotCardWindow.scala rename to src/main/scala/ocelot/desktop/windows/OcelotInterfaceWindow.scala index ab14aef..483ad49 100644 --- a/src/main/scala/ocelot/desktop/ui/widget/card/OcelotCardWindow.scala +++ b/src/main/scala/ocelot/desktop/windows/OcelotInterfaceWindow.scala @@ -1,15 +1,14 @@ -package ocelot.desktop.ui.widget.card +package ocelot.desktop.windows import ocelot.desktop.geometry.{Padding2D, Size2D} -import ocelot.desktop.inventory.item.OcelotCardItem import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout} import ocelot.desktop.ui.widget.LogWidget.LogEntry -import ocelot.desktop.ui.widget.{Button, Checkbox, Filler, Label, LogWidget, PaddingBox, TextInput, Widget} import ocelot.desktop.ui.widget.window.PanelWindow -import ocelot.desktop.util.Orientation +import ocelot.desktop.ui.widget.{Button, Checkbox, Filler, Label, LogWidget, PaddingBox, TextInput, Widget} +import ocelot.desktop.util.{OcelotInterfaceLogStorage, Orientation} -class OcelotCardWindow(item: OcelotCardItem) extends PanelWindow { - override protected def title: String = s"Ocelot card ${item.component.node.address}" +class OcelotInterfaceWindow(storage: OcelotInterfaceLogStorage) extends PanelWindow { + override protected def title: String = s"${storage.name} ${storage.ocelotInterface.node.address}" private val logWidget: LogWidget = new LogWidget { override protected def textWidth: Int = 50 @@ -30,7 +29,7 @@ class OcelotCardWindow(item: OcelotCardItem) extends PanelWindow { } children :+= new Label { - override def text: String = s"Messages: ${item.entryCount} / ${item.messageLimit}" + override def text: String = s"Messages: ${storage.entryCount} / ${storage.messageLimit}" } children :+= new Widget { @@ -46,7 +45,7 @@ class OcelotCardWindow(item: OcelotCardItem) extends PanelWindow { Padding2D(right = 12) ) - children :+= new TextInput(item.messageLimit.toString) { + children :+= new TextInput(storage.messageLimit.toString) { private def parseInput(text: String): Option[Int] = text.toIntOption.filter(_ > 0) override def minimumSize: Size2D = super.minimumSize.copy(width = 60) @@ -57,7 +56,7 @@ class OcelotCardWindow(item: OcelotCardItem) extends PanelWindow { override def onConfirm(): Unit = { for (messageLimit <- parseInput(text)) { - item.messageLimit = messageLimit + storage.messageLimit = messageLimit } super.onConfirm() @@ -82,7 +81,7 @@ class OcelotCardWindow(item: OcelotCardItem) extends PanelWindow { }) private def clear(): Unit = { - item.clear() + storage.clear() } def onMessagesAdded(entries: Iterable[LogEntry]): Unit = { @@ -94,6 +93,6 @@ class OcelotCardWindow(item: OcelotCardItem) extends PanelWindow { } def pushLine(line: String): Unit = { - item.component.pushMessage(line) + storage.ocelotInterface.pushMessage(line) } }