mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
parent
a609ae8cb4
commit
e994011cd9
BIN
sprites/nodes/ocelot-block/Default.png
Normal file
BIN
sprites/nodes/ocelot-block/Default.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 644 B |
BIN
sprites/nodes/ocelot-block/Rx.png
Normal file
BIN
sprites/nodes/ocelot-block/Rx.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 B |
BIN
sprites/nodes/ocelot-block/Tx.png
Normal file
BIN
sprites/nodes/ocelot-block/Tx.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 101 B |
Binary file not shown.
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 147 KiB |
@ -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
|
||||
|
||||
22
src/main/scala/ocelot/desktop/entity/OcelotBlock.scala
Normal file
22
src/main/scala/ocelot/desktop/entity/OcelotBlock.scala
Normal file
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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(_)))
|
||||
}
|
||||
|
||||
@ -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(_)))
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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())
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
{
|
||||
|
||||
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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"
|
||||
}
|
||||
@ -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")
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user